我见过太多团队在 requirements.txt 上翻车。一个新同事拉下代码,跑 pip install -r requirements.txt,直接报错。你检查了半天,发现是某个人本地装了个新包,忘了更新文件。这种场景太常见了。
为什么 requirements.txt 会变成雷区
很多人直接 pip freeze > requirements.txt 完事。这个命令会把本地所有包都列进去,连系统级别的依赖都带上了。你的项目可能只用了 Flask,结果文件里多出来几十个无关包。别人装的时候要么装不上,要么版本冲突。
另一个坑是不锁定版本号。有人写 Flask 不加版本号。这等于告诉别人你不管版本。几个月后 Flask 更新了重大改动,别人的代码直接跑不起来。还有些人写 Flask>=2.0,这种宽松限制也容易出问题。
多人协作时怎么避免冲突
一个原则是只记录项目直接依赖的包。比如你用 Django 和 requests,就只写这两个。不要写它们的子依赖。这样 requirements.txt 就很干净,别人一眼能看懂项目需要什么。
版本号要写死。比如 Django==4.2.7,requests==2.31.0。这样所有人都用同一个版本。偶尔需要升级时,专门做一次更新,大家一起测试。
可以考虑拆分成两个文件。一个叫 requirements.txt 放生产环境需要的包。另一个叫 requirements-dev.txt 放测试工具、代码检查工具这类开发专用包。生产环境不要装 pytest 这些无关的东西。
实际案例看问题
有个项目组五六个人一起开发。有个人在本地装了个 pandas 做数据分析,随手 pip freeze 更新了 requirements.txt。其他人部署时发现多了 numpy、pandas 一堆包,虽然也能运行,但部署时间翻倍。后来查了半天才发现是某个人无心的操作。
还有一次,有人写 celery>=5.0,另一个人的环境刚好装了 5.3 版本。结果 celery 在 5.2 版本后改了某个 API 的行为,导致任务队列出问题。查了两天才发现是版本差。如果当时锁定成 celery==5.1.2,几秒钟就解决了。
把依赖管理纳入工作流
我建议团队在 git 提交规范里加一条:每次添加或更新依赖包,必须同时更新 requirements.txt 并说明变更原因。不要在 commit message 里只写“修复bug”,要写“添加了 redis 依赖用于缓存”这种清楚的话。
用代码审查来卡住不规范的 requirements.txt。如果看到有人 pip freeze 完直接提交,要求他手动清理清楚只有项目需要的包。多来几次,大家就养成习惯了。
也可以用 pip-tools 这类工具。它会分析你的代码里 import 了哪些包,自动生成锁文件。团队里统一用 pip-compile 来生成 requirements.txt,确保每个人操作一致。
环境隔离不能省
每个项目都要用虚拟环境。不管用 venv 还是 conda,目的就是不把项目依赖和系统 Python 混在一起。有些人觉得麻烦,直接在全局环境装包。这种习惯迟早出问题。两个项目用不同版本的 Flask,全局环境根本没法处理这种冲突。
在项目根目录放个 .python-version 文件,指定 Python 版本。这样 pyenv 这类工具能自动切版本。配合 requirements.txt 锁死的包版本,换台机器也能一秒还原环境。
依赖管理没有银弹。但至少要做对基础操作。写清楚 requirements.txt 不是多麻烦的事,省下的排查时间远超写文件的时间。下次你看到那种几百行的 requirements.txt,就该知道这个团队在依赖管理上走过弯路。