应使用pyenv隔离管理多版本Python,避免修改系统Python;通过shim机制按需调用版本,需配置shell初始化;安装依赖头文件,版本优先级为local>global;shebang须明确指定python2/python3;venv必须基于pyenv对应版本创建;跨版本需注意print、input、编码、bytes处理差异。

用 pyenv 管理多版本,别碰系统 Python
系统自带的 python 是操作系统依赖的一部分,硬改 /usr/bin/python 软链接或卸载重装极易导致包管理器(如 apt、dnf)崩溃。真正安全的做法是让所有用户级 Python 版本完全隔离于系统之外。pyenv 正是为此设计:它不修改系统路径,只通过 shim 机制在 $PATH 前置注入轻量代理脚本,按需调用对应版本。
- 安装后必须把
pyenv init输出的 shell 片段加进~/.bashrc或~/.zshrc,否则pyenv命令本身都不可用 -
pyenv install 2.7.18和pyenv install 3.9.18会分别编译安装,源码编译时若缺zlib-dev、openssl-dev等头文件,会报错zipimport.ZipImportError: can't decompress data或ModuleNotFoundError: No module named '_ssl' - 全局版本用
pyenv global 3.9.18,项目级用pyenv local 2.7.18(会在当前目录生成.python-version),后者优先级更高
#!/usr/bin/env python 不再可靠,必须写死或用 pyenv 注入
脚本开头的 #!/usr/bin/env python 会查 $PATH 找第一个 python,但这个“第一个”取决于你是否激活了 pyenv 的 shell 配置。没加载 pyenv init 的 shell 中,它仍可能指向系统 /usr/bin/python(常是 Python 2.7),导致 Python 3 脚本语法报错;而即使加载了,env 也不识别 pyenv 的版本切换逻辑——它只认 PATH 中可执行文件名。
- 生产脚本必须明确写成
#!/usr/bin/env python3或#!/usr/bin/env python2,避免歧义 - 开发中想保持灵活性,可用
pyenv exec python script.py强制指定版本,绕过 shebang - 某些 IDE(如 VS Code)的终端未继承 shell 的
pyenv环境变量,需在设置里启用"terminal.integrated.env.linux"手动注入PYENV_VERSION
虚拟环境必须和 pyenv 版本对齐,venv 不认 pyenv 的软链接
pyenv 创建的每个 Python 版本都有独立的二进制路径(如 ~/.pyenv/versions/3.8.10/bin/python),而 python -m venv 或 virtualenv 是靠调用具体解释器来构建环境的。如果误用系统 python3 去创建 venv,哪怕当前 pyenv version 显示是 3.11,该 venv 仍绑定系统 Python,后续 pip install 可能升级错位置的包。
- 创建前先确认:运行
which python,输出必须是~/.pyenv/versions/xxx/bin/python形式 - 推荐用
pyenv virtualenv 3.11.5 myproject,它本质是封装了virtualenv并自动绑定正确解释器 - 激活后
which pip应返回~/.pyenv/versions/3.11.5/envs/myproject/bin/pip,若仍是/usr/bin/pip,说明环境没激活或创建错了
Python 2 与 3 的 print、input、编码差异仍在影响脚本互通
即便版本切换顺畅,混用代码仍会出 runtime 错误。比如 Python 2 的 input() 等价于 Python 3 的 eval(input()),直接传字符串会触发 NameError;Python 2 默认 str 是字节流,Python 3 默认 str 是 Unicode,用 open() 读文本不加 encoding 参数,在 Python 3 下极大概率抛 UnicodeDecodeError。
立即学习“Python免费学习笔记(深入)”;
- 跨版本脚本不要依赖
print "hello",统一用from __future__ import print_function(仅限 Python 2.6+) - 读写文件务必显式声明编码:
open("f.txt", "r", encoding="utf-8"),Python 2 不支持该参数,需用io.open()替代 - 网络请求返回的
bytes对象(如requests.get().content)在 Python 2 里可直接当str处理,Python 3 必须先.decode("utf-8")
最麻烦的不是装几个版本,而是不同版本下同一行代码的行为差异藏得深,跑一次不报错,换台机器或换个输入就崩——盯住 print、input、文件 IO、网络响应这四类操作,比反复检查 pyenv 配置更省时间。


















