pip-tools 能生成真正可复现的 requirements.txt,因为它从 requirements.in 递归解析依赖树并锁定唯一版本组合,支持哈希校验、约束文件和自定义配置,而 pip freeze 仅输出当前环境快照,无法保证跨环境一致性。

pip-tools 能生成真正可复现的 requirements.txt,但前提是必须理解它和 pip install 的根本区别:它不安装包,只解析、锁定、输出;且默认不处理 setup.py 或 pyproject.toml 中的依赖。
为什么直接 pip freeze 不够用
你执行 pip freeze > requirements.txt 得到的清单,是当前环境里所有已安装包的快照,包含间接依赖(transitive deps)、版本冲突时的妥协结果,甚至可能混入开发时临时装的调试工具。它无法保证在另一台机器上 pip install -r requirements.txt 装出完全一致的环境——尤其当某个包在 PyPI 上发布了新补丁版本(比如 requests==2.31.0 升级为 2.31.1),而你的 freeze 文件没锁死小版本。
-
pip-tools从顶层requirements.in出发,递归解析所有依赖树,再根据兼容性约束求解出唯一满足条件的版本组合 - 它默认启用
--pre禁用、--index-url可配、支持-c constraints.txt引入全局约束 - 输出的
requirements.txt每行都带哈希(--generate-hashes),校验包完整性
pip-compile 基本工作流
核心命令是 pip-compile,它读 requirements.in,写 requirements.txt。别手写 .in 文件——那是你的“源声明”,只写你明确需要的包,比如:
django>=4.2 psycopg2-binary requests[security]
然后运行:
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
pip-compile --generate-hashes --output-file=requirements.txt requirements.in
-
--generate-hashes必加:否则 CI/CD 中无法验证包来源是否被篡改 - 不要省略
--output-file:默认输出到 stdout,容易误操作 - 如果项目用
pyproject.toml定义依赖(如 Poetry 或 PEP 621),pip-compile默认不识别——需额外加--config-file=pyproject.toml并确认工具段落含[tool.pip-compile] - 想排除某个子依赖?用
pip-compile --exclude django,但要小心破坏依赖图
常见报错与绕过方式
最常遇到的是 ResolutionImpossible 错误,典型提示像:
Could not find a version that matches requests!=2.29.0,>=2.25.0,==2.31.0
这说明不同顶层依赖对同一包提出了互斥版本要求。解决思路不是强行降级,而是:
- 检查
requirements.in是否显式写了冲突约束(比如同时写了requests>=2.25和some-pkg==1.0,而后者只兼容requests) - 用
pip-compile --rebuild --upgrade强制重新求解,跳过缓存 - 临时加
--allow-unsafe查看哪些包被标记为“unsafe”(如setuptools、wheel),它们通常不该出现在生产锁定文件中 - 若依赖来自私有索引,确保
--index-url正确且网络可达,否则会静默跳过包导致解析失败
和 CI/CD 集成的关键细节
在 GitHub Actions 或 GitLab CI 中,不能只跑 pip-compile 就完事。必须验证生成的 requirements.txt 是否真的能装通:
- 先
pip install pip-tools(别假设基础镜像自带) - 运行
pip-compile后,立即执行pip install --no-deps --ignore-installed -r requirements.txt—— 这步跳过依赖检查,只校验哈希和下载可用性 - 真正的安装测试应另起干净虚拟环境:
python -m venv .test-env && .test-env/bin/pip install -r requirements.txt - 注意
pip-compile默认使用系统 Python 的pip版本,若项目要求pip>=23.0,得先升级再编译,否则可能因解析逻辑差异导致锁定结果不同
真正难的不是生成文件,而是让团队所有人、所有环境都用同一套 pip-compile 版本(建议锁死 pip-tools==7.3.0)并统一配置参数——少一个 --generate-hashes,就等于放弃确定性。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










