Python 虚拟环境到底怎么选?venv/conda/pipenv/poetry 一张对比表 + 9 个踩坑

12 阅读5分钟

先给结论

如果你只想要一句话:普通项目用 venv + pip freeze,发布型项目用 poetry,科学计算/需要换 Python 解释器的用 conda,pipenv 已经不推荐新项目使用。

虚拟环境解决的是同一个问题——让不同项目用不同版本的依赖,互不污染。但**"要不要锁版本""要不要管 Python 解释器""要不要顺手打包"**,这三个需求决定了你该选哪个工具。选错不会立刻报错,但会在半年后以"我这里能跑,线上跑不起来"的形式还给你。


一、四张牌分别是什么

1. venv(标准库,Python 3.3+ 自带)

python -m venv .venv
source .venv/bin/activate        # macOS / Linux
.venv\Scripts\activate           # Windows

venv 只做一件事:创建一个隔离的目录,里面有独立的 python 和 pip。它不解析依赖、不锁版本、不管 Python 解释器版本——它是"地基",不是"管家"。

2. conda(Anaconda / Miniconda)

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)

pipenv install requests
pipenv lock

曾经被 PyPA 官方推荐,把 pip 和 venv 包成一层。问题是依赖解析慢、维护节奏变慢,2020 年之后社区基本转向了 poetry / uv。

4. poetry(pyproject.toml + poetry.lock)

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 的锁文件依然是最稳的。


二、一张对比表(选型时看这张就够了)

维度venvcondapipenvpoetry
依赖锁定❌ 需手动 pip freeze✅ environment.yml✅ Pipfile.lock✅ poetry.lock
管 Python 版本❌✅❌❌(需配合 pyenv)
依赖冲突检测❌ 装了才知道✅ 解析较慢✅ 慢✅ 快且清晰
打包发布❌❌⚠️ 勉强✅ 原生支持
科学计算包⚠️ 可能要本地编译✅ 预编译二进制⚠️⚠️
学习成本极低中中中偏高
配置文件无environment.ymlPipfilepyproject.toml
推荐场景脚本 / 小项目 / 容器数据科学 / 多语言环境老项目维护库 / 服务 / 要发布的包

一句话总结:小项目别上 poetry,数据科学别硬用 venv,要发包就别用 venv 硬凑。


三、9 个真实踩坑(按出现频率排序)

坑 1:激活了环境,pip 还是装到全局

pip install requests

python -m pip install requests

python -m pip 保证用的是当前 python 对应的那个 pip。验证方式:

which python    # macOS/Linux
where python    # Windows

如果输出的路径不在 .venv 里,说明你没真的激活环境。

坑 2:Windows PowerShell 禁止运行激活脚本

无法加载文件 .venv\Scripts\Activate.ps1,因为在此系统上禁止运行脚本。

原因是 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,装到的是今天的最新版,可能与你的代码不兼容。

pip freeze > requirements.txt

pip install pip-chill && pip-chill --no-version > requirements.txt

生产环境锁全量,开发环境可以只锁顶层。

坑 5:pip freeze 把本地路径也写进去了

pip install -e .        # 开发模式安装
pip freeze              # 输出里出现 -e git+https://... 或 file:///...

这种 requirements.txt 换台机器就装不上。解决:发布前用 pip list --format=freeze 检查,或直接用 poetry 管理。

坑 6:虚拟环境目录被提交到 Git

.gitignore
.venv/
venv/
env/
__pycache__/

.venv 里可能有几百 MB,而且路径写死在脚本里,提交上去既污染仓库又无法复用。

坑 7:venv 不能直接"移动"

mv myproject /new/path      # 环境直接失效

因为激活脚本和 pyvenv.cfg 里写死了绝对路径。要移动就重建:

rm -rf .venv && python -m venv .venv && python -m pip install -r requirements.txt

坑 8:Docker 里面多此一举地建 venv

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 版本把命令搞混

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)

python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python -m pip freeze > requirements.txt   # 装完后重新锁

方案 B:发布型项目(poetry)

[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"
poetry install      # 按 poetry.lock 精确安装
poetry update       # 更新并重新生成锁

方案 C:数据科学(conda)

name: ml
channels: [conda-forge]
dependencies:
  - python=3.11
  - numpy
  - pandas
  - scikit-learn
conda env create -f environment.yml
conda env update -f environment.yml --prune

五、排查清单(环境问题 5 分钟定位)

  1. which python / where python —— 确认解释器路径 ✅
  2. python -V —— 确认版本 ✅
  3. python -m pip -V —— 确认 pip 归属 ✅
  4. pip list —— 看装了什么、版本对不对 ✅
  5. 删掉重建 —— 90% 的疑难杂症最后都是这一步解决的 ✅

小结

虚拟环境的核心不是"用哪个工具",而是**"依赖是否可复现"。venv 解决的是隔离,requirements.txt / poetry.lock / environment.yml 解决的才是可复现**——后者才是团队协作和线上部署真正需要的东西。

记住三条:① 永远用 python -m pip;② 生产环境必须锁全量版本;③ 环境坏了就重建,别在坏环境里打补丁。


你现在的团队用的是哪一套? 评论区说说你踩过最离谱的环境坑,我看看能不能整理成第二期。