__ _ _ / _| ___ _ __(_) | | |_ / _ \| '__| | | | _| (_) | | | | | |_| \___/|_| |_|_|
Python 的项目管理一直给人一种“工具很多,但总差一点统一感”的感觉。写一个小脚本时,pip install 好像就够了;项目稍微复杂一点,就会开始遇到 Python 版本、虚拟环境、运行依赖、开发依赖、构建配置、锁文件这些问题。再往深度学习或者科学计算方向走,还会碰到 CUDA、C/C++ 库、系统依赖这些不完全属于 Python 的东西。
这篇文章不打算整理一个完整工具大全,只是简单记录一下 Python 项目管理的历史脉络,以及现在比较常见的几类工具应该如何理解。
Python 早期更多是作为脚本语言被使用,项目形态不像今天这样复杂。后来生态不断扩大,包分发、虚拟环境、构建系统、依赖锁定等需求逐渐出现,于是工具也像“补丁”一样一层层长出来。
比较典型的分工是:
pip 负责安装包venv 负责创建虚拟环境requirements.txt 记录一组依赖setup.py / setup.cfg 负责打包和构建配置pyproject.toml 作为统一配置入口这些工具本身都能解决问题,但组合起来以后,新手很容易困惑:到底应该把依赖写在哪里?虚拟环境要不要提交?开发依赖和运行依赖怎么分?部署时怎样保证别人安装到同一批版本?
先看官方和 PyPA 体系下的基础工具。
venv 是 Python 标准库提供的虚拟环境工具。它的作用是给项目创建一个隔离目录,里面有自己的 Python 解释器入口和 site-packages,避免不同项目之间的依赖互相污染。
shpython -m venv .venv source .venv/bin/activate
.venv 通常放在项目目录里,但不提交到 Git。虚拟环境应该被看作可以随时删除并重建的产物,真正需要提交的是依赖声明文件。
pip 则是最基础的包安装工具:
shpython -m pip install requests python -m pip install -r requirements.txt
而 pyproject.toml 是现代 Python 项目越来越核心的配置入口。它可以用来声明构建系统、项目元信息、运行依赖,也可以放一些开发工具的配置,例如 pytest、ruff、black 等。
一个很简化的例子:
toml[project] name = "example" version = "0.1.0" requires-python = ">=3.11" dependencies = [ "requests>=2.32.0", ] [dependency-groups] dev = [ "pytest>=8.0.0", "ruff>=0.8.0", ]
可以粗略理解为:venv 管环境,pip 装包,pyproject.toml 描述项目。它们构成了现代 Python 项目管理的基础。
Conda 不是 Python 官方项目管理工具,但它在数据科学、深度学习、科学计算里非常常见。
它和 venv + pip 最大的区别在于:Conda 管理的不只是 Python 包,还可以管理 Python 解释器本身,以及 C/C++ 库、CUDA、R、命令行工具等非 Python 依赖。对于 NumPy、PyTorch、CUDA 这类带有复杂二进制依赖的场景,Conda 往往能减少不少环境配置上的麻烦。
常见用法类似这样:
shconda create -n demo python=3.11 conda activate demo conda install numpy
如果项目非常依赖底层二进制环境,Conda 依然是一个很实用的选择。但它和 PyPI / PyPA 体系是两套生态:Conda 有自己的 channel、包格式和依赖解析方式。在一个环境里混用 conda install 和 pip install 也不是不行,只是最好先用 Conda 安装重型依赖,再用 pip 补充 Conda 中没有的 Python 包,避免依赖解析互相打架。
近几年比较流行的一个工具是 uv。它由 Rust 编写,定位是高速 Python 包和项目管理器。和只把它理解成“更快的 pip”相比,我觉得更准确的说法是:uv 试图把建环境、装依赖、写配置、生成锁文件、运行命令这些流程收进同一个工具里。
一个新项目可以这样开始:
shuv init demo cd demo uv add requests uv add --dev pytest ruff uv run python main.py
执行这些命令后,uv 会维护 pyproject.toml,并生成 uv.lock 来锁定依赖版本。之后其他人拿到项目时,可以通过:
shuv sync
把环境同步到锁文件描述的状态。
需要注意的是,uv.lock 应该通过 uv lock、uv sync、uv run 或 uv add 这类项目命令生成和更新。uv pip compile 更像是兼容 pip-tools 的用法,通常用于把依赖编译成 requirements.txt 这类文件,而不是生成 uv.lock。
shuv lock uv sync # requirements 风格的锁定输出 uv pip compile pyproject.toml -o requirements.txt
如果是新项目,我现在会更倾向于直接用 uv init / uv add / uv sync 这条项目工作流;如果是老项目,还在用 requirements.txt,则可以先用 uv pip install -r requirements.txt 或 uv pip compile 逐步迁移。
如果只是普通 Python 项目,可以先考虑:
pyproject.toml 记录项目元信息和依赖.venv 隔离环境uv 管理依赖、锁文件和运行命令如果是深度学习、科学计算,或者项目明显依赖 CUDA、系统库、跨语言包,那么 Conda 依然值得考虑。
也就是说,Python 项目管理并没有一个绝对统一的答案。更现实的理解是:官方标准在逐渐收敛到 pyproject.toml,社区工具则在尝试把分散的流程变得更顺手。对个人项目来说,先把“依赖写清楚、环境可重建、版本能锁住”做好,就已经能避免很多后续麻烦。