Skip to content

多版本共存方案 ​

在现代 Python 开发中,同一台机器上往往需要同时存在多个 Python 版本:旧项目依赖 3.9,新项目使用 3.12,还要验证 3.13 的新特性。本节将系统讲解 Windows 的 py launcher、macOS/Linux 的 pyenv、以及 uv 三种多版本共存方案,并给出选择建议与切换技巧。

前置知识

阅读本节前,建议先了解:环境变量配置

基础概念 ​

多版本共存(Multiple Version Coexistence)的核心是:让每个版本拥有独立的安装目录与可执行文件名,再通过启动器或路径切换决定「当前使用哪个版本」。

概念说明
版本启动器(Launcher)如 Windows 的 py、pyenv 的 shim,负责按规则选择解释器
Shim代理可执行文件,拦截调用并转发到真实解释器
符号链接(Symbolic Link)指向实际解释器的快捷引用
全局版本未指定项目时的默认版本
局部版本某目录(项目)内生效的版本
虚拟环境(Virtual Environment)与解释器版本解耦的依赖隔离层

三层隔离关系需要区分清楚:

text
解释器版本(pyenv / launcher 管理)
    └── 项目依赖(venv / virtualenv 管理)
            └── 依赖清单(requirements.txt / pyproject.toml 固定)

版本管理与虚拟环境不是一回事

pyenv 决定「用哪个 Python 解释器」,venv 决定「用哪一套 site-packages」。二者互补,不可互相替代。典型做法是:pyenv 切换解释器版本 → 在该版本下创建 venv → 在 venv 内安装依赖。

语法与用法 ​

Windows:py launcher ​

bash
# 列出所有已注册版本
py --list

# 使用指定版本
py -3.12 script.py
py -3.13 -m pip install requests

# 使用默认(最高)版本
py script.py

# 查看某版本路径
py -3.12 -c "import sys; print(sys.executable)"

macOS / Linux:pyenv ​

bash
# 安装多个版本
pyenv install 3.11.9
pyenv install 3.12.7
pyenv install 3.13.0

# 查看已安装
pyenv versions

# 设置全局版本
pyenv global 3.12.7

# 设置项目局部版本
cd ~/projects/legacy && pyenv local 3.11.9

# 查看当前生效版本
pyenv version

跨平台:uv ​

bash
# 安装多个 Python
uv python install 3.11 3.12 3.13

# 列出已管理版本
uv python list

# 固定项目版本
uv python pin 3.12.7

详细说明 ​

方案一:Windows py launcher ​

Windows 官方安装程序会自动安装 py.exe(Py Launcher),位于 C:\Windows\py.exe。它会扫描注册表与 PATH 中所有已安装的 Python。

bash
# 完整版本列表(含 32/64 位)
py --list

# 输出示例:
#  -V:3.13 *        Python 3.13 (64-bit)
#  -V:3.12          Python 3.12 (64-bit)
#  -V:3.11          Python 3.11 (64-bit)
#  -V:3.10-32       Python 3.10 (32-bit)

在脚本中声明所需版本,有两种方式:

python
# 方式一:shebang 行(脚本首行)
#! python3.12
"""shebang.py —— py launcher 会读取首行决定版本。"""

import sys

print(f"当前版本:{sys.version.split()[0]}")
text
# 方式二:py.ini 配置文件(位于 %LOCALAPPDATA%\py.ini)
[defaults]
python=3.12
python3=3.12
ini
; 也可以为特定脚本路径指定版本
[commands]
C:\scripts\legacy_tool.py=3.9

用 py launcher 创建虚拟环境

py -3.12 -m venv .venv 会用 3.12 创建虚拟环境,是 Windows 上最简洁的多版本 + 隔离方案。

方案二:pyenv(macOS / Linux) ​

pyenv 通过 shim 机制工作:在 ~/.pyenv/shims 目录中放置大量代理可执行文件(python、pip 等),这些 shim 被加入 PATH 最前面;调用时 shim 根据当前目录与规则决定真实的解释器路径。

版本选择优先级(从高到低):

优先级来源说明
1PYENV_VERSION 环境变量临时指定,最高优先
2.python-version(当前目录)pyenv local 生成
3.python-version(父目录逐级向上查找)向上递归
4~/.pyenv/versionpyenv global 生成
5system系统 Python
bash
# 临时覆盖(仅当前命令)
PYENV_VERSION=3.11.9 python --version

# 生成 .python-version
cd ~/projects/demo
pyenv local 3.12.7
cat .python-version
# 输出:3.12.7

# 设置全局默认
pyenv global 3.12.7

# 恢复为系统 Python
pyenv global system

# 查看某个版本的实际路径
pyenv which python

~/.zshrc 或 ~/.bashrc 中的必要配置:

bash
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

pyenv 的 shim 依赖 PATH 顺序

eval "$(pyenv init -)" 会把 ~/.pyenv/shims 放到 PATH 最前。若之后又追加了其他 Python 目录到 PATH 前面,shim 会被绕过,导致 pyenv global 看似无效。排查时用 which python 确认是否命中 ~/.pyenv/shims/python。

方案三:uv(现代一体化方案) ​

uv 用 Rust 实现,同时管理 Python 版本与项目依赖,性能远超 pyenv。

bash
# 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# 或
brew install uv

# 下载多个 Python(存放在 ~/.local/share/uv/python)
uv python install 3.11 3.12 3.13

# 列出
uv python list

# 固定项目版本,生成 .python-version
cd ~/projects/demo
uv python pin 3.12.7

# 创建虚拟环境(自动使用 pinned 版本)
uv venv

# 运行脚本(自动选择正确解释器)
uv run python -c "import sys; print(sys.version)"

uv 管理的 Python 存储路径:

text
~/.local/share/uv/python/
├── cpython-3.11.9-macos-aarch64-none/
├── cpython-3.12.7-macos-aarch64-none/
└── cpython-3.13.0-macos-aarch64-none/

方案对比 ​

维度py launcherpyenvuv
平台仅 WindowsmacOS / Linux(Windows 有限支持)全平台
实现C++ 启动器Shell + shimRust
管理对象已安装的 Python编译安装的 Python下载/管理的 Python + 依赖
切换粒度命令行参数全局 / 目录 / 环境变量项目
安装速度不适用(不自带安装)慢(需本地编译)极快(下载预编译)
是否管理依赖否否是
学习成本低中低

实战示例 ​

案例一:Windows 上三版本共存并各建虚拟环境 ​

powershell
# 1. 安装三个版本
winget install --id Python.Python.3.11 -e
winget install --id Python.Python.3.12 -e
winget install --id Python.Python.3.13 -e

# 2. 确认注册情况
py --list
#  -V:3.13 *        Python 3.13 (64-bit)
#  -V:3.12          Python 3.12 (64-bit)
#  -V:3.11          Python 3.11 (64-bit)

# 3. 为不同项目创建虚拟环境
mkdir D:\projects\legacy, D:\projects\modern
cd D:\projects\legacy
py -3.11 -m venv .venv
cd D:\projects\modern
py -3.13 -m venv .venv

# 4. 验证 legacy 项目
cd D:\projects\legacy
.\.venv\Scripts\Activate.ps1
python --version    # Python 3.11.x
deactivate

# 5. 验证 modern 项目
cd D:\projects\modern
.\.venv\Scripts\Activate.ps1
python --version    # Python 3.13.x
deactivate

案例二:macOS 用 pyenv 管理并配合 venv ​

bash
#!/bin/bash
# setup-multi-python.sh —— macOS 多版本环境搭建
set -euo pipefail

# 1. 安装 pyenv
brew install pyenv

# 2. 配置 shell
grep -q 'pyenv init' ~/.zshrc || cat >> ~/.zshrc <<'EOF'
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
EOF
source ~/.zshrc

# 3. 安装三个版本
for v in 3.11.9 3.12.7 3.13.0; do
    pyenv install -s "$v"
done

# 4. 全局默认 3.12.7
pyenv global 3.12.7

# 5. 旧项目固定 3.11.9
mkdir -p ~/projects/legacy && cd ~/projects/legacy
pyenv local 3.11.9
python -m venv .venv
source .venv/bin/activate
python --version   # Python 3.11.9
deactivate

# 6. 新项目固定 3.13.0
mkdir -p ~/projects/modern && cd ~/projects/modern
pyenv local 3.13.0
python -m venv .venv
source .venv/bin/activate
python --version   # Python 3.13.0
deactivate

echo "多版本环境就绪"
pyenv versions

案例三:Linux 服务器上用 update-alternatives 切换 ​

bash
# 假设已编译安装了 3.11.9 与 3.12.7

# 注册候选版本
sudo update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.11 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.12 2

# 交互式选择
sudo update-alternatives --config python3

# 验证
python3 --version

# 恢复为发行版默认
sudo update-alternatives --auto python3

不要在服务器上随意切换系统 python3

apt、yum、cloud-init 等工具依赖特定 Python。若必须切换,请先确认这些工具在当前版本下仍能运行,或改用 pyenv/venv 隔离。

案例四:CI 中矩阵测试多版本 ​

yaml
# .github/workflows/test.yml
name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.11", "3.12", "3.13"]
    steps:
      - uses: actions/checkout@v4
      - name: 设置 Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - name: 安装依赖
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: 运行测试
        run: pytest -q

CI 中无需 pyenv

GitHub Actions 的 actions/setup-python 已内置多版本切换能力,直接声明 python-version 即可,不必在 CI 中使用 pyenv。

注意事项 ​

  • 优先使用启动器而非改 PATH:py -3.12、pyenv local、uv run 都比手工改 PATH 可靠。
  • Windows 注意应用执行别名:python.exe 别名会绕过 py launcher,需在设置中关闭。
  • pyenv 编译耗时:每个版本需本地编译,可用 pyenv install --list 查看源码缓存。
  • .python-version 要入库:项目固定版本声明应提交到 Git,保证团队一致。
  • 不要删除系统 Python:多版本共存的前提是保留系统版本。
  • 注意版本兼容性:不同小版本可能行为差异,见 Python 版本生命周期。

常见问题排查表:

现象原因解决
pyenv global 不生效shim 未在 PATH 前面检查 eval "$(pyenv init -)"
py --list 缺版本未注册到注册表重装该版本并勾选注册
venv 版本不对创建时用错解释器用 py -3.x -m venv 明确指定
uv python install 慢网络问题配置 UV_PYTHON_INSTALL_MIRROR
多个 shim 冲突重复安装版本管理器只保留一种方案

最佳实践 ​

  • 只选一种版本管理方案:Windows 用 py launcher,macOS/Linux 用 pyenv 或 uv,避免多套 shim 冲突。
  • 项目内固定版本:提交 .python-version 与 pyproject.toml 的 requires-python。
  • 版本 + 虚拟环境双层隔离:pyenv/uv 管解释器,venv 管依赖。
  • 用 uv 提升效率:新项目优先考虑 uv,安装与解析都更快。
  • CI 用矩阵覆盖多版本:尽早发现兼容性问题。
  • 保持版本栈精简:本地保留 2~3 个版本即可,过多徒增维护成本。
  • 定期清理:pyenv uninstall 或 uv python uninstall 移除不再使用的版本。

下一节

继续学习:IDLE 与交互式解释器

参考链接 ​