使用 pyenv 管理 Python 版本和虚拟环境

本文简要介绍了如何使用 pyenv 和 virtualenv 对 Python 版本及虚拟环境进行管理。

Python 版本管理

为什么要进行 Python 版本管理:

  • 系统自带 Python 版本老旧,某些项目依赖 Python 新版本的特性。如 macOS Sonoma 14.0 系统自带 Python 版本为 3.9.6,而 Stable Diffusion web UI 要求 Python 3.10.6 版本。
    1
    2
    3
    4
    5
    
    $ which python3
    /usr/bin/python3
    
    $ python3 -V
    Python 3.9.6
  • 系统自带 Python 版本为系统各功能正常运行所需,贸然升级可能导致系统崩溃故障。
  • 不同项目所依赖的 Python 版本可能不同,因此需要安装多个版本的 Python 并管理,如 Python 3.9 和 Python 3.10 等。
  • 不同项目所依赖的 Python 包/模组 的版本也可能不同,因此可能还需安装不同版本的 Python 依赖包并管理,如:pytorch 1.11 和 pytorch 2.0 等。

Python 版本管理器的功能:

  • 将 Python 安装在用户目录而非系统目录下
  • 安装多个不同版本的 Python
  • 指定需要使用的 Python 版本
  • 在安装的多个 Python 版本间切换

pyenv 是一个简易的 Python 版本管理器。我们可以使用 pyenv 在 Python 的多个不同版本之间轻松切换。同时 pyenv 的设计简易、务实,遵循只做好一件事 (Do one thing well) 的 UNIX 哲学1

准备工作

由于 pyenv 从源代码编译构建 Python,因此我们需要提前安装那些构建 Python 所需的依赖项。 在不同环境下构建 Python 所需的依赖项可能有所不同,具体请参考 pyenv 给出的构建环境参考。 本文仅介绍在 macOS 中使用 Homebrew 安装构建 Python 所需的依赖项。

1
2
3
4
5
6
7
8
# 安装 Xcode 命令行工具(Xcode Command Line Tools)
$ xcode-select --install

# 安装其他所需依赖项
# $ brew install openssl readline sqlite3 xz zlib tcl-tk
# 经测试 macOS 系统已默认安装 readline sqlite3 zlib 三个包
# 此处无需重复安装,可顺利编译构建 Python
$ brew install openssl xz tcl-tk

安装 pyenv

在 macOS 中可通过 Homebrew 安装 pyenv

1
2
$ brew update
$ brew install pyenv

然后为 pyenv 配置 Shell 环境, 对于 macOS 中 Terminal 默认使用的 Zsh,在 ~/.zshrc 中添加:

1
2
3
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

启用刚添加的 Shell 环境配置

1
2
3
4
$ source ~/.zshrc

# 也可以
$ exec "$SHELL"

使用 pyenv 安装 Python

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 列出所有可通过 pyenv 安装的 Python 版本
$ pyenv install --list

# 安装所需版本的 Python
$ pyenv install 3.11
# pyenv 会检索并安装符合要求的最新版 Python,目前为 3.11.5

# 查看所有通过 pyenv 安装的 Python 版本
$ pyenv versions
* system (set by /Users/user/.pyenv/version)
  3.11.5

# 查看 Python 的实际安装位置
$ ls ~/.pyenv/version
3.11.5

# 查看当前激活的 Python 版本及其被那个文件或环境变量设置
$ pyenv version
system (set by /Users/user/.pyenv/version)
注意
若安装 Python 过程中报错,可查看 pyenv 官方文档中安装额外的 Python 版本以及常见安装问题获取帮助。

报错:No module named ‘_lzma’

如果通过 pyenv 安装 Python 时报错:

1
2
3
4
......
	from _lzma import *
ModuleNotFoundError: No module named '_lzma'
**WARNING**: The Python lzma extension was not compiled. Missing the lzma lib?

可能是因为缺少 xz 库。可以通过 Homebrew 安装 xz 库,并且使用 pyenv 卸载并重新安装所需版本的 Python。

1
2
3
brew install xz
pyenv uninstall 3.11.5
pyenv install 3.11

源码下载过慢

使用 pyenv 安装 Python 时,默认从 Python 官网下载指定版本,若下载速度过慢,可手动从官网下载所需版本的源代码 Python-3.11.5.tra.xz~/.pyenv/cache 目录下,再执行相应的安装命令。

指定 Python 版本

虽然我们已经通过 pyenv 安装了 Python 3.11.5,但未经指定的情况下,目前 Python 仍默认为系统自带的 3.9.6 版本。 为方便说明,我们继续通过 pyenv 安装多个不同版本的 Python

1
2
$ pyenv install 3.12-dev
$ pyenv install 3.10.13

pyenv 提供了三个不同的命令来指定使用的 Python 版本:

global

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看全局默认 Python 版本
$ pyenv global

# 将全局默认 Python 指定为 3.10.13
$ pyenv global 3.10.13
$ pyenv version
3.10.13 (set by /Users/user/.pyenv/version)
$ cat ~/.pyenv/version
3.10.13

# 将全局默认 Python 指定回系统自带版本
$ pyenv global system

若使用上述 pyenv global 命令将全局默认的 Python 版本指定为 3.10.13。 该命令会新建 ~/.pyenv/version 文件并将其内容设定为 3.10.13,此时在命令行中系统内任意目录下执行 pythonpip 等命令时,默认调用 Python 3.10.13。

local

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 查看局部 Python 版本
$ pyenv local

# 将局部 Python 指定为 3.11.5
$ cd project
$ pyenv local 3.11.5
$ pyenv version
3.11.5 (set by /Users/user/project/.python-version)
$ cat .python-version
3.11.5

# 撤销之前指定过的局部 Python 的版本
$ pyenv local --unset

若使用上述 pyenv local 命令将局部 Python 版本指定为 3.11.5,该命令将覆盖由 pyenv global 命令指定的全局默认版本。 该命令会在当前目录下新建一个 .python-version 文件并将其内容设定为 3.11.5,当用户在当前目录及其所有子目录下执行 pythonpip 等命令时,将调用 Python 3.11.5。

shell

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看当前 Shell 的 Python 版本
$ pyenv shell

# 将当前 Shell 的 Python 版本指定为 3.12-dev
$ pyenv shell 3.12-dev
$ pyenv version
3.12-dev (set by PYENV_VERSION environment variable)
$ echo $PYENV_VERSION
3.12-dev

# 撤销之前指定过的当前 Shell 中的 Python 版本
$ pyenv shell --unset

若使用上述 pyenv shell 命令将当前 Shell 中的 Python 版本指定为 3.12-dev,该命令将覆盖由 pyenv global 命令指定的全局默认版本以及由 pyenv local 命令指定的局部版本。 该命令会将环境变量 PYENV_VERSION 设定为 3.12-dev,用户在当前 Shell 中执行 pythonpip 等命令时,将调用 Python 3.12-dev。

指定顺序

pyenv 会按照如下顺序依次查询,并将按照查询到的第一个设定,激活相应的 Python 版本。

顺序 参数存储位置 相关命令
1 $PYENV_VERSION pyenv shell
2 .python-version pyenv local
3 ~/.pyenv/version pyenv global
4 System Python System Python

安装 pyenv-virtualenv

Python 虚拟环境相当于一个独立的 Python 版本,有自己独立的目录,也可独立安装第三方库,而不会对外界产生影响。这样不同项目都有互相独立的运行环境,非常便于项目开发。

pyenv-virtualenv 是 pyenv 的一个插件,用于管理虚拟环境。可通过 Homebrow 方便的安装: 在 macOS 中可通过 Homebrow 安装 pyenv-virtualenv

1
2
3
4
5
$ brew update
$ brew install pyenv-virtualenv

# 确认 pyenv-virtualenv 安装成功
$ which pyenv-virtualenv

然后为 pyenv-virtualenv 配置 Shell 环境, 对于 macOS 中 Terminal 默认使用的 Zsh,在 ~/.zshrc 中添加:

1
eval "$(pyenv virtualenv-init -)"

pyenv-virtualenv 的使用

创建虚拟环境

1
2
3
4
$ pyenv virtualenv [Python_version] <environment_name>

# 列出创建的所有虚拟环境
$ pyenv virtualenvs

pyenv-virtualenv 会基于给定的 Python 版本,创建一个名为 environment_name 的环境,若省略 [Python_version] 则基于当前激活的 Python 版本创建环境。

pyenv 会将创建的虚拟环境当作不同版本的 Python 对待,如 pyenv versions 命令同时会列出已经创建的虚拟环境。

激活虚拟环境

上一步中创建的虚拟环境的使用方法与之前使用 pyenv 安装的不同版本的 Python 一样,都可以通过 pyenv global/local/shell 命令来指定如何激活。

此外虚拟环境还可以手动激活和关闭:

1
2
3
4
5
# 手动激活虚拟环境
$ pyenv activate <environment_mane>

# 手动关闭激活的虚拟环境
$ pyenv deactivate

删除虚拟环境

1
2
3
4
5
# 通过 pyenv 删除虚拟环境
$ pyenv uninstall <environment_mane>

# 通过 virtualenv-delete 删除虚拟环境
$ pyenv virtualenv-delete <environment_mane>

将虚拟环境应用至项目

在 Project 项目中创建并自动激活基于 Python 3.11.5 的虚拟环境。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 创建项目目录
$ mkdir Project

# 进入项目目录
$ cd Project

# 创建项目所属的虚拟环境
$ pyenv virtualenv 3.11.5 Project

# 设定进入项目目录后自动激活相应的虚拟环境
$ pyenv local Project
# 激活虚拟环境后,pyenv 会在命令提示符前自动添加当前激活的 Python 版本名
(Project) $ pyenv version
Project (set by /Users/user/Project/.python-version)

# 退出项目目录后自动退出虚拟环境
(Project) $ cd ..
# 退出虚拟环境后,命令提示符前的 Python 版本名称会被自动去除
$ pyenv version
system (set by /Users/user/.pyenv/version)

可使用相同方式在其他项目目录中创建并激活基于不同 Python 版本的虚拟环境。

【参考】

0%