Skip to content

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 为例。

bash
# 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
# 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 补丁版本。

bash
# 查看所有可安装的版本(列表很长,可配合 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 使用完全相同的解释器版本。

text
# 文件内容示例:./.python-version
3.12.7
bash
# 在项目根目录查看该文件的生效结果
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 20

pyenv 的版本解析是"就近原则":它在当前目录逐级向上查找 .python-version,遇到第一个即停止,不会继续向上;只有整棵目录树都没有时才会回退到全局配置。

bash
# 目录树示例
# /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 用户可单独安装。

bash
# 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 直接下载源码在国内可能很慢,可改用镜像加速。

bash
# 临时指定镜像源(以阿里云为例)
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 为例)。

bash
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-dev

macOS 上则需要安装 Xcode 命令行工具,pyenv 会依赖它们进行编译。

bash
xcode-select --install

# 若缺少 zlib、readline 等,可让 pyenv 借用 Homebrew 提供的库
brew install openssl readline sqlite3 xz zlib tcl-tk
# 新版 pyenv 会自动探测 Homebrew 前缀,一般无需再手动设置 LDFLAGS

调试 pyenv 的常见手段 ​

bash
# 查看当前 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)。

bash
# 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)
text
# 目录结构示意
legacy-app/
├── .python-version      # legacy-app-3.9(虚拟环境名)
├── requirements.txt
└── src/
new-app/
├── .python-version      # 3.13.1
├── pyproject.toml
└── src/

示例二:用 Python 脚本汇总当前环境的版本信息 ​

pyenv 自带的信息也可以被程序读取,用于写入日志或生成环境报告。

python
"""生成当前 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()
bash
$ 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 使用同款版本,可避免"本地能跑、线上报错"。

yaml
# .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 版本

参考链接 ​