别再纠结“哪个工具最好”,先问一句:你现在到底缺哪一层?缺隔离,用 venv;缺安装,用 pip;缺跨语言二进制依赖,用 conda;缺依赖锁定和打包,用 Poetry;想把整条工程链尽量收进一个工具,再考虑 uv。
“我刚开始学 Python,到底该装 conda 还是 pip?”
这是新手最常问的问题之一,也最难直接用一句“选 A”或“选 B”来回答。原因很简单:这两个工具压根不在同一层,谈不上真正的二选一。
pip 负责装包,conda 负责环境和跨语言依赖。在 conda 环境里继续用 pip,其实非常常见。它不是配错了,而是很多项目本来就这么用。
这篇文章不打算再做一轮“工具优缺点排行榜”,而是把 pip、venv、conda、Poetry、uv 放回它们各自的位置,再给出四个可以直接照着选的场景。
01 五个工具,各管一层
先别急着比较,先把位置摆对。这五个工具解决的,本来就不是同一个问题:
| 工具 |
管的是哪一层 |
官方定位一句话 |
| venv |
环境隔离 |
Python 标准库自带,创建互不干扰、可丢弃重建的独立环境 |
| pip |
包安装 |
从 PyPI 安装 Python 包,Python 官方默认安装器 |
| conda |
跨语言包与依赖 |
官方定位是“对任何语言提供包、依赖和环境管理” |
| Poetry |
依赖+打包 |
声明依赖、锁定版本、构建发布,一个工作流 |
| uv |
单工具收敛 |
Rust 实现,官方自述要替换上面一串工具 |

venv 和 pip 是 Python 官方的基础组合;conda 是科学计算社区常用的跨语言方案;Poetry 解决的是纯 Python 项目的工程化;uv 则是 2024 年之后出现的新变量。
它们看上去都叫“Python 环境工具”,但其实更像五件用途不同的工具。只是平时经常出现在同一篇安装教程里,才容易被误认为是在争同一个位置。
这里先记住一个判断原则:两个工具能不能互相替代,先看它们是不是在同一层。
venv 和 conda 都能做环境隔离,勉强算有竞争关系;pip 和 Poetry 都涉及 Python 包安装,也有一部分重叠。但 venv 和 pip 本来就是互补的,Poetry 和 conda 更不是同一种东西。
把层次分清以后,后面的选型就没那么乱了。
02 最基础的一对:venv 管隔离,pip 管安装
先把这一对记住,剩下几个工具会容易理解很多。
venv 是 Python 标准库自带的虚拟环境模块(3.3 加入,3.5 起官方推荐使用)。它只做一件事:给当前项目建一个独立目录,里面有自己的 Python 解释器和 site-packages,不去碰其他项目的环境。
官方文档把它定义为“轻量级”、可以整体删除重建的环境,也不建议把整个 venv 目录提交进 Git。
它的工作方式没有看上去那么神秘。venv 目录里会有一个 pyvenv.cfg,记录这个环境是基于哪个 Python 创建的;bin/ 目录下则放着这个环境自己的解释器。运行时,只要 sys.prefix != sys.base_prefix,Python 就知道自己正处在虚拟环境里。
而且,虚拟环境也不是非得“激活”以后才能用。你完全可以直接写完整路径,调用环境里的解释器。
pip 则是 Python 官方的包安装器,负责从 PyPI 下载并安装包。执行 pip install requests 时,包会被装进当前 Python 环境的 site-packages:你在 venv 里执行,它就装进 venv;你在系统环境里执行,它就装进系统环境。
换句话说,pip 负责“往哪里装东西”,但那个“哪里”是不是独立的,不归它管。
最小可用组合就是下面这样,这也是本次环境里实际验证过的命令:
# 创建虚拟环境(本次环境中验证:Python 3.11.15 创建成功)
python3 -m venv .venv
# 激活
source .venv/bin/activate
# 激活后,pip 自动装进这个环境,而不是系统环境(官方文档行为)
pip install requests
为什么一定要隔离?因为系统里的 Python 通常不只归你管。Homebrew、apt 或系统更新都可能改它。你直接在全局环境里一路 pip install,短期看很省事,时间一长就容易出问题:一个项目需要新版本,另一个项目偏偏依赖旧版本,装完这个,那个就坏了。
venv 的做法很直接:一个项目一个环境。真乱了就删掉重建,成本通常比继续排查全局环境低得多。
这里有两个边界要分清。
第一,venv 只解决“隔离”,不负责决定“装什么”和“装哪个版本”。
第二,requirements.txt 只锁直接依赖,不会自动锁住完整的传递依赖树。你写了 requests,它还会带进 urllib3、certifi 等间接依赖,但这些不会自然出现在 requirements.txt 里。换个时间、换台机器重装,间接依赖版本可能已经变了,环境也就跟着“漂”了。
Poetry 和 uv 之所以出现,很大程度上就是为了处理这件事:用 lockfile 把整棵依赖树一起锁住。
03 conda:不是 Python 专属,是跨语言管家
conda 和 pip 的差别,不只是“功能更多一点”。它们的官方定位从一开始就不一样。
conda 官方把自己定义为“对任何语言提供包、依赖和环境管理”。它不只管 Python,还能处理 C/C++、R,以及 CUDA 这类二进制库。
这也是科学计算和机器学习项目经常离不开 conda 的原因。numpy、pytorch 的 CPU/GPU 版本、R 包,背后往往不只是几个 Python 文件,还牵涉编译好的二进制依赖。只靠 pip,很多时候并不好装对。
conda 自己也能创建环境,例如 conda create -n。它和 venv 有点像,但管得更宽,也更重:不仅能隔离包,还能直接管理 Python 解释器版本,并在建环境时一起装好一批二进制依赖。
新版本 conda 还换用了更快的确定性求解器 libmamba。本次写作环境中,conda 26.3.2 的默认 solver 已经是 libmamba。
# 创建一个带指定 Python 版本的科学计算环境(官方命令示例)
conda create -n ml python=3.11 numpy pytorch
conda activate ml
conda 的代价也很明显:首次解析偏慢,环境体积更大,在国内使用时通常还要配置镜像源。
所以它更适合“项目里确实有跨语言二进制依赖”的场景,而不是为了装一个 requests,就先搬来一整套 conda。
还有一个很常见的误解,需要单独说清楚:conda 环境里完全可以继续用 pip。
conda 管环境和二进制依赖,pip 管 PyPI 上的 Python 包,这两个通道本来就可以共存。科学计算项目里,常见的组合就是 conda 建环境、处理 CUDA 等底层依赖,再用 pip 或 uv 安装 Python 包。
真正容易出问题的,不是“混用”本身,而是同一个包在两个通道之间反复横跳。今天 conda install,明天又 pip install 覆盖同一批包,版本冲突才会慢慢冒出来。
04 Poetry:把依赖+锁定+打包收进一个工作流
Poetry 更适合纯 Python 项目。它把依赖声明、版本锁定、构建和发布收进了一套工作流里。
项目配置写在 pyproject.toml 中——这是近几年 Python 生态逐渐统一起来的标准配置文件,也在慢慢替代老式的 setup.py。完整依赖树则记录在 poetry.lock 里。
Poetry 官方最核心的承诺,是通过 lockfile 保证可重复安装。同一份 lock 文件,在不同机器上安装出来的环境应该保持一致。它解决的,正是很多团队都遇到过的那句:“我这台能跑,怎么到你那台就不行了?”
Poetry 还直接支持把项目构建成可分发的包,执行 poetry publish 就可以发布到 PyPI。对需要交付给别人使用的 Python 库来说,这条链路确实比较顺。
# 官方文档示例(Poetry 要求 Python 3.10+;本文写作环境未安装 Poetry,未做本地运行)
poetry new my-lib
cd my-lib
poetry add requests
poetry install
不过,Poetry 的边界也很清楚:它解决的是纯 Python 项目工程化,不负责 CUDA、R 这类跨语言依赖。
项目需要原生二进制库时,更常见的做法是 conda 管底层,Poetry 管 Python 层。两者是配合关系,不必硬做二选一。
05 uv:一个 Rust 工具,官方自述要顶替一串
uv 是 2024 年之后 Python 工具链里的新面孔。它由 Rust 编写,定位是包管理器和项目管理器。
官方文档的说法很直接:希望用一个工具替换 pip、pip-tools、pipx、poetry、pyenv、twine、virtualenv 等一串工具。它提供通用 lockfile,也保留了和 pip 兼容的 uv pip 接口。
这意味着,你不一定要先改变原来的使用习惯。原来怎么写 pip 命令,现在可以先换成 uv 的兼容接口,优先吃到速度提升。官方自报速度比 pip 快 10-100 倍——这是官方披露的基准,本文没有单独复测。
uv 大致有两种用法,也对应两种不同的迁移方式:
- 兼容模式:用
uv pip install -r requirements.txt 替换 pip,命令习惯基本不变,先解决安装速度;
- 项目模式:用
uv init + uv add 管理项目和 lockfile,接手 Poetry 那部分工作,同时还能管理 Python 版本和命令行工具,对应原来 pipx、pyenv 的位置。
# 官方文档命令示例;uv venv 在本次写作环境中验证可用
uv venv .venv
uv pip install -r requirements.txt # 兼容 pip 的命令习惯
uv add requests # 项目级依赖管理,等价于 poetry add
安装 uv 不需要先装 Rust。官方支持 macOS、Linux 和 Windows,可以使用官方安装脚本,也可以直接 pip install uv。
除了包管理,它还能安装和运行命令行工具,也能直接管理 Python 版本。这才是“一个工具替换一串工具”具体落到使用层面的含义。
不过,uv 也有两个边界不能忽略。
第一,10-100x 是官方给出的 warm-cache 对比,不是独立第三方横评。引用这个数字时要说明口径,不能写成“我们实测”。
第二,uv 主要收敛的是 Python 工具链,并不替代 conda 的跨语言二进制能力。科学计算项目里,一个很实际的组合仍然是 conda 管 Python 和 CUDA 环境,uv 负责在这个环境里更快地安装 Python 包。
06 我该用哪个?四个场景直接抄答案
| 场景 |
首选组合 |
理由 |
| 新开一个普通 Python 项目 |
python3 -m venv + pip |
官方默认、零额外安装,够用 |
| 换新机器/团队协作 |
Poetry(或 uv 项目模式) |
lockfile 锁定完整依赖树,装出来一致 |
| 科学计算/机器学习 |
conda 建环境 + pip(或 uv)装 Python 包 |
跨语言二进制依赖只有 conda 能管 |
| 开发要发布的 Python 库 |
Poetry |
依赖+构建+发布一个工作流 |

再把这四种情况拆开说一遍:
- 新开普通项目:
python3 -m venv .venv && source .venv/bin/activate && pip install ...,三行命令就能开始。它不要求额外安装工具,任何常见 Python 环境都能用。大多数个人脚本和小工具,到这里其实已经够了。
- 换新机器/团队协作:这时最重要的不是“能装上”,而是“每个人装出来都一样”。venv + requirements.txt 仍可能出现依赖漂移,Poetry 或 uv 的 lockfile 能锁住完整依赖树。团队项目做到这一步,后面会少很多环境问题。
- 科学计算/机器学习:只要项目碰到 GPU、C 扩展或 R,通常就需要 conda 打底。因为它处理的是 PyPI 上不存在,或者仅靠 pip 很难装稳的二进制依赖。Python 包部分继续用 pip 或 uv 都可以。
- 开发要发布的库:Poetry 能把
pyproject.toml、lockfile、构建和发布串起来。poetry publish 可以直接发到 PyPI,poetry build 也能生成 sdist 和 wheel。
判断时其实不用背太多规则。先看项目里有没有“Python 之外的二进制依赖”:有,就优先让 conda 打底。再看是否要求“可重复安装”:需要,就使用带 lockfile 的 Poetry 或 uv。两者都没有,venv 加 pip 已经足够。
07 三个最常踩的坑,怎么避开
-
在 conda 环境里使用 pip,并不等于配置错误。 conda 管环境,pip 管 PyPI 包,两个通道同时存在,是科学计算项目的常见状态。真正的问题是来回修改同一批包:一会儿 conda install,一会儿 pip install。更稳妥的做法是,环境交给 conda,Python 包尽量固定走一个通道(uv/pip)。安装前可以先用 conda list | grep <包名> 看看这个包现在由哪个通道管理。
-
uv 不是 conda 的替代品。 uv 再快,也不负责 CUDA、R 这类跨语言依赖。看到“uv 可以替换 pip/Poetry”,就顺手把 conda 也删掉,是这两年很常见的误读。反过来也一样:项目用了 conda,并不妨碍继续用 uv。它在 conda 的 Python 环境里照样可以工作。
-
Poetry 主要管 Python 包。 poetry add 不能替你处理 CUDA 版 PyTorch 背后的二进制调度。项目需要原生依赖时,仍然更适合让 conda 管底层,Poetry 或 uv 管 Python 层。另外,Poetry 要求 Python 3.10+,老系统上最好先确认解释器版本,再决定是否使用。
08 写在最后
以后再遇到“我到底该装哪个”,不妨先把问题换一下:我现在缺的,到底是哪一层?
- 缺隔离 →
python3 -m venv
- 缺安装 → pip(或 uv pip)
- 缺跨语言依赖 → conda
- 缺锁定和打包 → Poetry
- 想一次收敛 → uv
这几个工具不是一道单选题,更像一套组合工具。先找到项目当前缺的那一层,再决定从哪个工具开始。
下一行命令该敲什么,不取决于谁最流行,而取决于你现在缺什么。
想了解更多 Python 工具链的实践经验?来云栈社区和开发者们一起聊聊。