最稳妥方案是用venv创建项目级隔离环境:进入项目目录执行python3 -m venv .venv,再source .venv/bin/activate激活,确保pip install仅影响当前环境;依赖管理推荐原生venv+requirements.txt而非pipenv或poetry。

用 venv 创建项目级隔离环境最稳妥
MacOS 自带 Python(如 python3.9),但直接用 pip install 装包会污染系统环境,不同项目依赖冲突时无从下手。推荐每个项目用 venv 独立管理——它轻量、标准、无需额外安装工具。
实操建议:
- 进项目目录后运行
python3 -m venv .venv(注意空格和点号),生成.venv文件夹 - 激活:执行
source .venv/bin/activate,终端提示符前会出现(.venv) - 此时
which python和which pip都指向.venv内路径,所有pip install只影响当前环境 - 退出用
deactivate,不卸载也不删除,下次source即可复用
常见错误:忘记激活就 pip install,结果装到系统 Python 里;或误删 .venv 后没重装依赖,导致 ImportError。
需要切换多个 Python 版本时,用 pyenv 管理解释器本身
venv 只能基于已有 Python 解释器建环境,但它不能帮你装 python3.11 或 python3.8。这时 pyenv 是更底层的解法:它不修改系统 PATH,而是按需编译/下载指定版本,并让 shell 动态切换 python 命令指向。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 用 Homebrew 安装:
brew install pyenv,然后在~/.zshrc加三行(官方文档有完整模板) - 查看可用版本:
pyenv install --list | grep "3\.[89]",装一个:pyenv install 3.11.9 - 设为全局默认:
pyenv global 3.11.9;只对当前目录生效:pyenv local 3.8.18(会在目录下生成.python-version) - 验证:
python --version应立刻反映变更,且which python指向~/.pyenv/shims/python
注意:不要用 sudo 运行 pyenv,否则权限错乱;macOS Sonoma 后部分 Xcode 命令行工具缺失会导致 pyenv install 失败,需先运行 xcode-select --install。
pip 和 pipenv 不是替代关系,别混用
有人想用 pipenv 替代 venv + pip,但在 macOS 上容易出问题:它内部仍调用 venv,但会自动生成 Pipfile 和锁文件,而 macOS 的默认 shell(zsh)对某些 pipenv 的子 shell 行为支持不稳定,常出现 CommandNotFoundError: 'pipenv' 或虚拟环境路径识别错误。
实操建议:
- 坚持用原生
venv+requirements.txt:激活后pip freeze > requirements.txt,新环境用pip install -r requirements.txt - 如果必须用
pipenv,确保用brew install pipenv安装(而非pip install pipenv),并避免在~根目录下运行pipenv install -
poetry同理,它在 macOS 上对 Apple Silicon(M1/M2/M3)芯片的二进制兼容性曾长期滞后,现在虽已改善,但小众包仍可能因编译失败卡住
依赖冲突排查时,优先看 sys.path 和 pip show
当 import 报错或版本不对,不是立刻重装,先确认 Python 正在用哪个环境、包装在哪了。macOS 下尤其容易因 shell 配置混乱导致看似激活了虚拟环境,实际仍走系统路径。
实操建议:
- 在 Python 交互式环境中运行:
import sys; print('\n'.join(sys.path)),检查第一项是否为.venv/lib/python3.x/site-packages - 查某个包装在哪、什么版本:
pip show requests,输出里的Location:必须落在当前虚拟环境路径内 - 如果
pip list显示的包比sys.path里能 import 的多,说明有路径未加载;反之则可能被其他同名包 shadow(比如/usr/local/lib下有旧版) - 临时调试可加
-v参数:python -v -c "import numpy",看它到底尝试了哪些路径
最容易被忽略的是 zsh 的 hash -d 缓存和 pyenv 的 shim 机制——改完 pyenv local 后不新开终端,which python 可能还是旧的。

















