pip-compile生成的requirements.txt仍装错版本,根本原因是pip默认启用--upgrade-strategy=eager且未强制--require-hashes;必须配合--no-deps、--no-cache-dir、指定--index-url等flag才能确保生产环境精确复现。

pip-tools 能真正锁定生产依赖,但前提是必须用对流程——直接 pip-compile requirements.in 不等于“精准锁定”,漏掉子依赖约束或忽略哈希校验都会让锁定失效。
为什么 pip-compile 生成的 requirements.txt 有时仍会装错版本?
常见现象是:本地 pip-compile 生成了带版本号的 requirements.txt,CI 环境执行 pip install -r requirements.txt 却装出了不同版本,甚至失败。根本原因不是 pip-tools 失效,而是没关掉 pip 的默认行为:
- pip 默认启用
--upgrade-strategy=eager,遇到已安装包会尝试升级到满足约束的最新版(哪怕requirements.txt写死了requests==2.28.1,若本地已有2.27.0,pip 可能跳过) - 未使用
--require-hashes时,pip 不校验包哈希,可能从镜像源下载被篡改或缓存污染的 wheel -
requirements.in里写了django>=4.2,但没加--generate-hashes,pip-compile就不会在输出中写哈希,后续 install 就不强制校验
如何生成带完整哈希、可复现的 requirements.txt?
关键不是多加参数,而是按顺序执行两步:先锁版本,再补哈希。单独跑 pip-compile --generate-hashes 并不能自动推导出所有传递依赖的哈希(尤其当源不可达时)。
- 第一步:用
pip-compile --no-emit-find-links --strip-extras requirements.in生成基础锁定文件(去掉--find-links避免混入私有源路径) - 第二步:在干净虚拟环境中,用
pip install --require-hashes -r requirements.txt验证是否真能装通;若报 “Hashes not found” 错误,说明某些包没被 pip-tools 收录哈希,此时要手动补全:pip-compile --generate-hashes --index-url https://pypi.org/simple/ requirements.in - 务必删掉
requirements.txt顶部的# This file is autogenerated by pip-compile注释行——部分 CI 工具会因注释行触发重生成逻辑
生产部署时 pip install 必须加哪些 flag?
只靠 pip install -r requirements.txt 是危险的,默认行为会绕过哈希、忽略约束冲突、甚至静默降级。生产环境必须显式禁用这些自由度:
立即学习“Python免费学习笔记(深入)”;
- 强制校验:加
--require-hashes(要求每行依赖都带--hash=sha256:...) - 禁止升级:加
--no-deps --no-cache-dir(避免 pip 自作主张装/升级依赖;--no-cache-dir防止用到本地脏缓存) - 指定源:加
--index-url https://pypi.org/simple/ --trusted-host pypi.org(避免 pip 自动 fallback 到不可控镜像) - 如果
requirements.txt含-e git+https://...这类 VCS 行,必须额外加--find-links和--allow-external(但更推荐把这类包提前 build 成 wheel 并放入私有源)
dev 依赖和 prod 依赖怎么安全分离?
很多人用 requirements-dev.in 继承 requirements.in,但 pip-compile 不支持 import 语法。实际可行的做法只有两种:
- 方案一(推荐):用
pip-compile --extra dev requirements.in,前提是requirements.in中用pytest; extra == "dev"这种 PEP 508 格式声明条件依赖,并在setup.py或pyproject.toml的[project.optional-dependencies]里定义dev组 - 方案二(简单粗暴):维护两个独立
.in文件,用pip-compile --output-file=requirements-prod.txt requirements-prod.in和pip-compile --output-file=requirements-dev.txt requirements-dev.in,并在requirements-dev.in第一行写-r requirements-prod.in(注意是.in,不是.txt) - 切记:不要在
requirements-prod.txt里留-r requirements-dev.txt—— 这会让生产环境意外装上 pytest、mypy 等非运行时依赖
最易被忽略的一点:pip-tools 锁定的是“当前 pip index 返回的版本”,如果你的网络环境或镜像源配置变了(比如公司内网镜像同步延迟),pip-compile 输出的结果就可能不同。真正的可重现性,需要固定 index-url + 固定 Python 版本 + 固定 pip-tools 版本(建议 pin 到 pip-tools==7.3.0 这类 patch 版本)。


















