2、Python版本管理:pyenv的安装与使用,多版本切换实战
做深度学习的人,谁还没被Python版本坑过几次?
我记得刚入行那会儿,项目A需要Python 3.6跑TensorFlow 1.x,项目B又非要Python 3.8才能装PyTorch 1.10。系统自带的Python 3.5卡在中间,改一个崩一个。折腾了一整天,最后把系统Python搞坏了,连yum都用不了。
后来我学乖了——版本管理工具必须安排上。今天聊的pyenv,就是我用了五年还在用的方案。
2.1 为什么非要用pyenv?
你可能会问:用Docker不也行吗?当然行。但日常开发中,你总得在本地跑脚本、调试代码、装包测试。每次改个版本就起容器,太沉了。
pyenv解决的是本地多版本共存的问题。它不碰系统Python,只在用户目录下管理所有版本。切换时改个环境变量就行,干净利落。
核心原理一句话:pyenv通过修改$PATH,把你想用的Python版本"插"到最前面。系统还是那个系统,但shell找到的Python已经变了。
2.2 安装pyenv
安装方式因系统而异。我主要在Linux和macOS上干活,Windows用户可以用WSL2,体验基本一致。
Linux / macOS
# 用官方安装脚本,一步到位
curl https://pyenv.run | bash
# 或者用Git克隆(网络不好时推荐)
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
装完后,需要把下面几行加到你的shell配置文件里(~/.bashrc、~/.zshrc都行):
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
然后重载配置:
source ~/.bashrc # 或 source ~/.zshrc
我的习惯:装完立刻跑 pyenv --version 确认安装成功。如果报错,八成是PATH没配对,检查一下 echo $PATH 里有没有 ~/.pyenv/bin。
Windows (WSL2)
Windows用户我建议直接用WSL2的Ubuntu。装好WSL2后,在Ubuntu终端里按Linux流程走就行。别在原生Windows上折腾pyenv,坑太多。
2.3 安装与卸载Python版本
装好pyenv后,先看看它能管哪些版本:
# 列出所有可安装的版本(超长列表)
pyenv install --list
# 只看3.x的最新稳定版
pyenv install --list | grep " 3\.[0-9]*\.[0-9]*$"
安装指定版本:
# 安装Python 3.9.18
pyenv install 3.9.18
# 安装Python 3.11.7
pyenv install 3.11.7
卸载也很简单:
pyenv uninstall 3.9.18
我曾经踩过的坑:在Ubuntu上装Python 3.10+时,如果系统缺少 libssl-dev、libbz2-dev 这些依赖,编译会报错。建议装之前先跑一遍:sudo apt-get install build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev curl libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev。别问我怎么知道的,问就是重装了三次。
2.4 多版本切换实战
版本装好了,怎么切?pyenv提供了三种作用域:
| 命令 | 作用域 | 优先级 | 典型场景 |
|---|---|---|---|
pyenv global |
整个用户环境 | 最低 | 设置默认Python版本 |
pyenv local |
当前目录(递归) | 中等 | 项目级版本锁定 |
pyenv shell |
当前shell会话 | 最高 | 临时测试 |
来看实战操作:
# 查看已安装的版本
pyenv versions
# 设置全局默认版本(比如3.11.7)
pyenv global 3.11.7
# 验证
python --version # 输出: Python 3.11.7
# 进入项目目录,锁定版本
cd ~/projects/old_project
pyenv local 3.9.18
# 这个目录下python自动变成3.9.18
python --version # 输出: Python 3.9.18
# 临时切到3.8.18测试
pyenv shell 3.8.18
python --version # 输出: Python 3.8.18
# 退出shell会话后,恢复local或global的设置
我的工作流:每个项目根目录下放一个 .python-version 文件(pyenv local 自动生成)。这样团队成员clone代码后,只要装了pyenv,进目录自动切版本。配合 .tool-versions 还能管其他语言的版本,不过那是asdf的事儿了。
2.5 与virtualenv/virtualenvwrapper配合
pyenv只管Python版本,不管虚拟环境。但实际项目中,你还需要隔离包依赖。我推荐用 pyenv-virtualenv 插件,把版本管理和虚拟环境合在一起。
安装插件:
# 用git克隆插件
git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
# 在shell配置里加上
eval "$(pyenv virtualenv-init -)"
创建和使用虚拟环境:
# 基于3.11.7创建虚拟环境,取名myenv
pyenv virtualenv 3.11.7 myenv
# 激活
pyenv activate myenv
# 退出
pyenv deactivate
# 也可以像切换版本一样用local
pyenv local myenv
说白了,pyenv virtualenv 就是把虚拟环境当成一个"伪版本"来管理。切换时连版本带环境一起换,省心。
2.6 知识体系总览
下面这张图帮你理清pyenv的核心逻辑:
2.7 常见问题与避坑
- 安装慢? 设置环境变量
PYTHON_BUILD_MIRROR_URL指向国内镜像,比如华为云或阿里云的Python源码镜像。 - 切换版本后pip报错? 检查一下
which pip指向的是不是当前版本的pip。有时候旧版本的pip缓存会捣乱,跑pip install --upgrade pip刷新一下。 - 系统Python被覆盖了? 别慌。pyenv只改当前用户的PATH,不会动
/usr/bin/python。想用系统Python时,用路径/usr/bin/python就行。 - zsh下补全失效? 确保
eval "$(pyenv init -)"在shell配置文件的末尾,别被其他配置覆盖了。
我曾经犯过的错:有次在服务器上直接 sudo pyenv global 3.9,结果sudo环境下的PATH和普通用户不一样,搞得crontab里的脚本全炸了。记住:别用sudo跑pyenv,它只管理当前用户的Python。
嗯,pyenv这块儿就这些。版本管理搞定了,后面装包、配环境才不闹心。你想想看,要是连Python版本都切不明白,深度学习框架那些依赖冲突还不得把人逼疯?