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的核心逻辑:

pyenv 核心知识体系 pyenv 版本管理 虚拟环境 插件生态 install / uninstall global / local / shell versions / version virtualenv 插件 activate / deactivate virtualenvs 列表 pyenv-virtualenv pyenv-update pyenv-which-ext 核心工作流 1. pyenv install 3.11.7 → 2. pyenv global 3.11.7 3. pyenv virtualenv 3.11.7 myenv → 4. pyenv local myenv 搞定!版本和环境一次锁定

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版本都切不明白,深度学习框架那些依赖冲突还不得把人逼疯?