pyenv 安装与使用
pyenv 是 Python 生态中最流行的版本管理器(Version Manager),它通过拦截 python、pip 等命令的查找路径,让你在同一个系统中自由切换多个 Python 版本。本节将带你从零安装 pyenv,并掌握其核心子命令、版本优先级规则与插件体系。
前置知识
阅读本节前,建议先了解:多版本共存方案
基础概念
版本管理器(Version Manager)是一类命令行工具,用于在同一台机器上安装、切换和隔离多个语言运行时版本。pyenv 用纯 Shell 脚本实现,不依赖编译产物,因此安装轻量、跨平台一致。
它的核心机制是在 PATH 最前面插入若干个 shim(垫片)目录。当你在终端输入 python 时,实际执行的是 ~/.pyenv/shims/python 这个 Shell 脚本,由它再根据当前生效的版本号转发到 ~/.pyenv/versions/<版本>/bin/python。版本的选择遵循一套优先级规则:环境变量 PYENV_VERSION 优先,其次是当前目录及其父目录中的 .python-version 文件,然后依次是全局配置文件 ~/.pyenv/version 与系统默认。
需要特别区分两个概念:pyenv 管理的是 Python 解释器本身(哪个二进制、哪个标准库),而虚拟环境(virtualenv)管理的是 每个项目的依赖集合。两者层次不同,可以叠加使用,互不冲突。
| 概念 | 管理对象 | 典型工具 | 作用范围 |
|---|---|---|---|
| 版本管理器 | 解释器二进制 | pyenv、asdf、uv | 系统/目录 |
| 虚拟环境 | 第三方依赖包 | venv、virtualenv、conda | 项目 |
| 包管理器 | 包的下载与解析 | pip、uv、poetry | 虚拟环境内 |
语法与用法
安装 pyenv 最推荐的方式是使用官方提供的 pyenv-installer 脚本或系统包管理器。以下以 macOS 与 Linux 为例。
# macOS:使用 Homebrew 安装
brew update
brew install pyenv
# Linux/macOS:使用官方安装脚本(会一并安装 pyenv-virtualenv 等插件)
curl -fsSL https://pyenv.run | bash
# 验证安装
pyenv --version
# pyenv 2.4.14
# 查看帮助
pyenv help
pyenv help install安装完成后,需要把 pyenv 的初始化代码写入 Shell 配置文件,否则每次打开终端都要手动加载。
# Bash 用户:写入 ~/.bashrc
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc
# Zsh 用户:写入 ~/.zshrc
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init - zsh)"' >> ~/.zshrc
# 让配置立即生效
source ~/.zshrc接下来是 pyenv 的核心命令。版本号支持前缀匹配,例如 3.12 会解析到最新的 3.12.x 补丁版本。
# 查看所有可安装的版本(列表很长,可配合 grep 过滤)
pyenv install --list
pyenv install --list | grep -E '^\s*3\.1[234]'
# 安装指定版本
pyenv install 3.12.7
pyenv install 3.13.1
# 查看本机已安装的版本(前面的 * 表示当前生效版本)
pyenv versions
# 设置全局默认版本(写入 ~/.pyenv/version)
pyenv global 3.12.7
# 设置当前目录的版本(写入 ./.python-version,会向上查找)
pyenv local 3.13.1
# 仅对当前 Shell 会话临时生效(可用 pyenv shell --unset 取消)
pyenv shell 3.13.1
# 查看当前生效的版本与来源
pyenv version
# 3.13.1 (set by /Users/demo/project/.python-version)
# 卸载某版本
pyenv uninstall 3.12.7详细说明
版本优先级与 .python-version 文件
pyenv 的版本解析有严格的优先级顺序,理解它有助于排查"为什么生效的不是我期望的版本"。
| 优先级 | 来源 | 生效范围 | 设置方式 |
|---|---|---|---|
| 1(最高) | PYENV_VERSION 环境变量 | 当前 Shell 会话 | pyenv shell 3.13.1 |
| 2 | 当前目录及父目录的 .python-version | 目录树 | pyenv local 3.13.1 |
| 3 | ~/.pyenv/version | 全局 | pyenv global 3.12.7 |
| 4(最低) | 系统自带的 python3 | 全局 | 无 |
.python-version 是一个纯文本文件,每行一个版本号。把该文件提交到 Git 仓库,可以让团队成员与 CI 使用完全相同的解释器版本。
# 文件内容示例:./.python-version
3.12.7# 在项目根目录查看该文件的生效结果
cat .python-version # 3.12.7
pyenv version # 3.12.7 (set by /Users/demo/project/.python-version)
# 查看某个命令实际对应的可执行文件路径
pyenv which python
# /Users/demo/.pyenv/versions/3.12.7/bin/python
# 查看 pyenv 的根目录与配置
pyenv root
# /Users/demo/.pyenv
# 查看所有 pyenv 变量设置
pyenv --version && pyenv commands | head -n 20pyenv 的版本解析是"就近原则":它在当前目录逐级向上查找 .python-version,遇到第一个即停止,不会继续向上;只有整棵目录树都没有时才会回退到全局配置。
# 目录树示例
# /Users/demo/
# .python-version -> 3.12.7(全局也在,但仅当子目录无文件时生效)
# work/
# new-app/
# .python-version -> 3.13.1 <- 在此目录及子目录生效
cd /Users/demo/work/new-app
pyenv version
# 3.13.1 (set by /Users/demo/work/new-app/.python-version)
cd /Users/demo/work
pyenv version
# 3.12.7 (set by /Users/demo/.pyenv/version)不要用 sudo 执行 pyenv
pyenv 会把版本安装到 $PYENV_ROOT/versions/ 下,若用 sudo 执行,文件属主会变成 root,后续普通用户将无法写入和卸载。因此绝不要写 sudo pyenv install。
插件体系:pyenv-virtualenv
pyenv 本体只管解释器,配套插件 pyenv-virtualenv 负责虚拟环境管理。使用 pyenv-installer 安装时会自动带上它;Homebrew 用户可单独安装。
# Homebrew 安装插件
brew install pyenv-virtualenv
# 在 Shell 配置中追加初始化
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zshrc
source ~/.zshrc
# 基于指定 Python 版本创建虚拟环境
pyenv virtualenv 3.12.7 myproject-3.12
# 列出所有 virtualenv
pyenv virtualenvs
# 激活与退出(进入目录自动激活需配合 pyenv-virtualenv-init)
pyenv activate myproject-3.12
pyenv deactivate
# 为该目录绑定虚拟环境(写入 .python-version,之后 cd 进来自动激活)
cd ~/work/myproject
pyenv local myproject-3.12
# 删除虚拟环境
pyenv virtualenv-delete myproject-3.12除了 pyenv-virtualenv,社区还有几个常用插件:
| 插件 | 作用 | 常用命令 |
|---|---|---|
| pyenv-update | 升级 pyenv 自身 | pyenv update |
| pyenv-doctor | 检查安装依赖是否齐全 | pyenv doctor |
| pyenv-ccache | 用 ccache 加速源码编译 | 自动生效 |
| pyenv-pip-rehash | 安装带入口点的包后自动 rehash | 自动生效 |
| pyenv-virtualenv | 管理虚拟环境 | pyenv virtualenv |
提高安装速度:镜像与编译依赖
从 python.org 直接下载源码在国内可能很慢,可改用镜像加速。
# 临时指定镜像源(以阿里云为例)
export PYTHON_BUILD_MIRROR_URL="https://npmmirror.com/mirrors/python"
pyenv install 3.12.7
# 永久写入 Shell 配置
echo 'export PYTHON_BUILD_MIRROR_URL="https://npmmirror.com/mirrors/python"' >> ~/.zshrc
# 若使用代理,也可通过 https_proxy 让下载走代理
export https_proxy="http://127.0.0.1:7890"
pyenv install 3.13.1在 Linux 上从源码编译需要先装好构建依赖(以 Debian/Ubuntu 为例)。
sudo apt update
sudo apt install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev libffi-dev \
liblzma-dev libncursesw5-dev xz-utils tk-devmacOS 上则需要安装 Xcode 命令行工具,pyenv 会依赖它们进行编译。
xcode-select --install
# 若缺少 zlib、readline 等,可让 pyenv 借用 Homebrew 提供的库
brew install openssl readline sqlite3 xz zlib tcl-tk
# 新版 pyenv 会自动探测 Homebrew 前缀,一般无需再手动设置 LDFLAGS调试 pyenv 的常见手段
# 查看当前 pyenv 的所有环境变量与路径
pyenv root
pyenv version
pyenv versions
pyenv which python
pyenv which pip
# 查看 shim 是否可正常转发(-v 会打印调用链)
pyenv shims --short
# 重新生成 shim(安装新命令行工具后执行)
pyenv rehash
# 查看某个版本对应的安装目录
pyenv prefix 3.12.7
# /Users/demo/.pyenv/versions/3.12.7实战示例
示例一:为多个项目隔离不同 Python 版本
假设你同时维护一个老项目(需要 3.9)和一个新项目(需要 3.13)。
# 1. 安装两个版本
pyenv install 3.9.20
pyenv install 3.13.1
# 2. 老项目:固定到 3.9 并创建独立虚拟环境
cd ~/work/legacy-app
pyenv local 3.9.20
pyenv virtualenv 3.9.20 legacy-app-3.9
pyenv local legacy-app-3.9
python -V
# Python 3.9.20
# 3. 新项目:固定到 3.13
cd ~/work/new-app
pyenv local 3.13.1
python -V
# Python 3.13.1
# 4. 回到全局,确认互不干扰
cd ~
pyenv version
# 3.12.7 (set by /Users/demo/.pyenv/version)# 目录结构示意
legacy-app/
├── .python-version # legacy-app-3.9(虚拟环境名)
├── requirements.txt
└── src/
new-app/
├── .python-version # 3.13.1
├── pyproject.toml
└── src/示例二:用 Python 脚本汇总当前环境的版本信息
pyenv 自带的信息也可以被程序读取,用于写入日志或生成环境报告。
"""生成当前 Python 环境摘要,便于排查"版本不匹配"问题。"""
import os
import platform
import sys
from pathlib import Path
def collect_env_info() -> dict[str, str]:
"""收集解释器与 pyenv 相关的环境信息。"""
pyenv_root = os.environ.get("PYENV_ROOT", str(Path.home() / ".pyenv"))
version_file = Path(".python-version")
return {
"python_version": sys.version.split()[0],
"implementation": platform.python_implementation(),
"executable": sys.executable,
"pyenv_root": pyenv_root,
"pyenv_version_env": os.environ.get("PYENV_VERSION", "<未设置>"),
"local_version_file": (
version_file.read_text(encoding="utf-8").strip()
if version_file.exists()
else "<无 .python-version>"
),
}
def main() -> None:
info = collect_env_info()
width = max(len(key) for key in info)
for key, value in info.items():
print(f"{key.ljust(width)} : {value}")
if __name__ == "__main__":
main()$ python env_report.py
python_version : 3.13.1
implementation : CPython
executable : /Users/demo/.pyenv/versions/3.13.1/bin/python
pyenv_root : /Users/demo/.pyenv
pyenv_version_env : <未设置>
local_version_file: 3.13.1示例三:让 CI 流水线与本地版本一致
在仓库中提交 .python-version,并让 CI 使用同款版本,可避免"本地能跑、线上报错"。
# .github/workflows/ci.yml(节选)
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 直接读取 .python-version,保证与开发者本地一致
- name: 安装 pyenv
run: |
curl -fsSL https://pyenv.run | bash
echo "$HOME/.pyenv/bin" >> "$GITHUB_PATH"
echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc
- name: 按 .python-version 安装 Python
run: |
source ~/.bashrc
pyenv install --skip-existing "$(cat .python-version)"
pyenv local "$(cat .python-version)"
python -V
- run: pip install -r requirements.txt && pytest注意事项
- shim 机制导致的问题:某些 IDE 或工具直接调用系统
/usr/bin/python3,绕过 shim。请在 IDE 中手动指定~/.pyenv/versions/<版本>/bin/python的绝对路径。 pyenv rehash容易忘记:通过pip install安装了带命令行入口的程序(如black、pytest)后,需要执行pyenv rehash才能通过 shim 找到它。若安装了pyenv-pip-rehash插件则会自动处理。pyenv global与pyenv local混用:一旦在某目录执行了pyenv local,该目录及所有子目录都会忽略global设置。排查异常版本时,先用pyenv version看清来源。- 不要同时用两种方式管理同一解释器:若已用 Homebrew 安装
python@3.12,再用 pyenv 装 3.12,两者PATH顺序会相互干扰。 .python-version与虚拟环境绑定:当文件里写的是虚拟环境名(如myproject-3.12)而非版本号时,必须先启用pyenv-virtualenv,否则 pyenv 会报 "version not installed"。- shell 配置顺序敏感:
eval "$(pyenv init -)"必须在PATH中已包含$PYENV_ROOT/bin之后执行,且应放在其他修改PATH的语句之后。 - 迁移到 uv 的场景:如果你主要做项目管理而非系统级切换,
uv python install也能安装解释器且速度更快,可参考 uv 工具链管理。
最佳实践
- 在项目根目录提交
.python-version,让版本要求可版本化、可评审。 - 用
pyenv-installer一次性装齐插件,避免后续零散补齐。 - 将
PYTHON_BUILD_MIRROR_URL写入 Shell 配置,在受网络限制的环境中显著提速。 - CI 中固定
--skip-existing,避免重复编译消耗流水线时间。 - 升级 Python 小版本(如 3.12.6 → 3.12.7)后可先用
pyenv versions确认旧版本仍在,再统一替换.python-version。 - 定期清理不再使用的版本:
pyenv uninstall <版本>释放磁盘空间。 - 团队统一使用同一版本管理器;若团队主用 asdf,可参考 asdf 管理 Python 版本 做取舍。
下一节
继续学习:asdf 管理 Python 版本