先给结论
如果你只想要一句话:普通项目用 venv + pip freeze,发布型项目用 poetry,科学计算/需要换 Python 解释器的用 conda,pipenv 已经不推荐新项目使用。
虚拟环境解决的是同一个问题------让不同项目用不同版本的依赖,互不污染。但**"要不要锁版本""要不要管 Python 解释器""要不要顺手打包"**,这三个需求决定了你该选哪个工具。选错不会立刻报错,但会在半年后以"我这里能跑,线上跑不起来"的形式还给你。
一、四张牌分别是什么
1. venv(标准库,Python 3.3+ 自带)
bash
python -m venv .venv
source .venv/bin/activate # macOS / Linux
.venv\Scripts\activate # Windows
venv 只做一件事:创建一个隔离的目录 ,里面有独立的 python 和 pip。它不解析依赖、不锁版本、不管 Python 解释器版本------它是"地基",不是"管家"。
2. conda(Anaconda / Miniconda)
bash
conda create -n myproj python=3.11
conda activate myproj
conda install numpy pandas
conda 的强项是:它连 Python 解释器本身都能换 ,而且装 numpy、scipy 这类带 C/Fortran 扩展的包时,会直接给你编译好的二进制(MKL 加速版),不用本地编译。
3. pipenv(Pipfile + Pipfile.lock)
bash
pipenv install requests
pipenv lock
曾经被 PyPA 官方推荐,把 pip 和 venv 包成一层。问题是依赖解析慢、维护节奏变慢,2020 年之后社区基本转向了 poetry / uv。
4. poetry(pyproject.toml + poetry.lock)
bash
poetry init
poetry add requests
poetry install
poetry 是目前最完整的方案 :依赖解析、精确锁版本、虚拟环境管理、打包发布一条龙,配置文件统一收敛到 pyproject.toml(PEP 518 标准)。
补充一句现实:2026 年很多团队已经换成
uv(Astral 出品,Rust 写的,解析和下载快一个数量级,uv venv/uv pip install兼容 pip 语义)。但uv目前更适合作为"更快的 pip",工程规范层面 poetry 的锁文件依然是最稳的。
二、一张对比表(选型时看这张就够了)
| 维度 | venv | conda | pipenv | poetry |
|---|---|---|---|---|
| 依赖锁定 | ❌ 需手动 pip freeze |
✅ environment.yml | ✅ Pipfile.lock | ✅ poetry.lock |
| 管 Python 版本 | ❌ | ✅ | ❌ | ❌(需配合 pyenv) |
| 依赖冲突检测 | ❌ 装了才知道 | ✅ 解析较慢 | ✅ 慢 | ✅ 快且清晰 |
| 打包发布 | ❌ | ❌ | ⚠️ 勉强 | ✅ 原生支持 |
| 科学计算包 | ⚠️ 可能要本地编译 | ✅ 预编译二进制 | ⚠️ | ⚠️ |
| 学习成本 | 极低 | 中 | 中 | 中偏高 |
| 配置文件 | 无 | environment.yml | Pipfile | pyproject.toml |
| 推荐场景 | 脚本 / 小项目 / 容器 | 数据科学 / 多语言环境 | 老项目维护 | 库 / 服务 / 要发布的包 |
一句话总结:小项目别上 poetry,数据科学别硬用 venv,要发包就别用 venv 硬凑。
三、9 个真实踩坑(按出现频率排序)
坑 1:激活了环境,pip 还是装到全局
bash
pip install requests
python -m pip install requests
python -m pip 保证用的是当前 python 对应的那个 pip。验证方式:
bash
which python # macOS/Linux
where python # Windows
如果输出的路径不在 .venv 里,说明你没真的激活环境。
坑 2:Windows PowerShell 禁止运行激活脚本
无法加载文件 .venv\Scripts\Activate.ps1,因为在此系统上禁止运行脚本。
原因是 PowerShell 的执行策略限制。解决(只对当前会话生效,不需要管理员):
powershell
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
.venv\Scripts\Activate.ps1
或者干脆用 CMD:.venv\Scripts\activate.bat。
坑 3:conda 和 pip 混用把环境搞坏
典型操作:先 conda install numpy,再 pip install numpy,结果两个 numpy 互相覆盖 ,报 ImportError: numpy.core.multiarray failed to import。
原则 :先 conda 装,再 pip 装;pip 只装 conda 里没有的包;不要用 pip 去升级 conda 装的包。
坑 4:requirements.txt 里不写版本
requests
flask
半年后别人 pip install -r requirements.txt,装到的是今天的最新版,可能与你的代码不兼容。
bash
pip freeze > requirements.txt
pip install pip-chill && pip-chill --no-version > requirements.txt
生产环境锁全量,开发环境可以只锁顶层。
坑 5:pip freeze 把本地路径也写进去了
bash
pip install -e . # 开发模式安装
pip freeze # 输出里出现 -e git+https://... 或 file:///...
这种 requirements.txt 换台机器就装不上。解决:发布前用 pip list --format=freeze 检查,或直接用 poetry 管理。
坑 6:虚拟环境目录被提交到 Git
bash
.gitignore
.venv/
venv/
env/
__pycache__/
.venv 里可能有几百 MB,而且路径写死在脚本里,提交上去既污染仓库又无法复用。
坑 7:venv 不能直接"移动"
bash
mv myproject /new/path # 环境直接失效
因为激活脚本和 pyvenv.cfg 里写死了绝对路径。要移动就重建:
bash
rm -rf .venv && python -m venv .venv && python -m pip install -r requirements.txt
坑 8:Docker 里面多此一举地建 venv
dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
容器本身就是隔离环境 ,再套一层 venv 只会增加镜像体积。但依赖必须锁定 (requirements.txt 要有版本号)。
坑 9:多 Python 版本把命令搞混
bash
python # 可能是 2.7,也可能没装
python3 # 3.x
py -3.11 # Windows 官方启动器
Windows 上推荐用 py -3.11 -m venv .venv ,能精确指定版本;macOS/Linux 建议装 pyenv 统一管理解释器,再用 python -m venv。
四、三套可直接抄的配置
方案 A:最小可用(venv)
bash
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python -m pip freeze > requirements.txt # 装完后重新锁
方案 B:发布型项目(poetry)
toml
[tool.poetry]
name = "myproj"
version = "0.1.0"
dependencies = { python = "^3.11", requests = "^2.32" }
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
bash
poetry install # 按 poetry.lock 精确安装
poetry update # 更新并重新生成锁
方案 C:数据科学(conda)
yaml
name: ml
channels: [conda-forge]
dependencies:
- python=3.11
- numpy
- pandas
- scikit-learn
bash
conda env create -f environment.yml
conda env update -f environment.yml --prune
五、排查清单(环境问题 5 分钟定位)
which python/where python------ 确认解释器路径 ✅python -V------ 确认版本 ✅python -m pip -V------ 确认 pip 归属 ✅pip list------ 看装了什么、版本对不对 ✅- 删掉重建 ------ 90% 的疑难杂症最后都是这一步解决的 ✅
小结
虚拟环境的核心不是"用哪个工具",而是**"依赖是否可复现"。venv 解决的是隔离,requirements.txt / poetry.lock / environment.yml 解决的才是可复现**------后者才是团队协作和线上部署真正需要的东西。
记住三条 :① 永远用 python -m pip;② 生产环境必须锁全量版本;③ 环境坏了就重建,别在坏环境里打补丁。
你现在的团队用的是哪一套? 评论区说说你踩过最离谱的环境坑,我看看能不能整理成第二期。