pip-compile 不生成结构,而是基于 requirements.in 求解唯一可复现带哈希的依赖树;需仅声明顶层依赖、用宽松约束、禁用粘贴 freeze 结果、分环境用 -r 引用、并显式指定 --output-file 和 --generate-hashes。

直接结论:pip-compile 本身不“生成结构”,它从 requirements.in 的声明出发,求解出唯一、可复现、带哈希的依赖树;所谓“高度确定性”,本质是靠约束写法 + 求解器行为 + 安装方式三者共同保障,缺一不可。
requirements.in 必须只写顶层依赖,且用宽松约束
很多人误以为把 pip freeze 输出粘贴进 requirements.in 就算完成声明——这反而让 pip-compile 失去求解空间,变成无意义的重写。真正起作用的是你写的那几行“意图”:
- 写
requests>=2.28.0,而不是requests==2.31.0;给 solver 留出在满足所有约束前提下选最优版本的余地 - 避免写死次版本号(如
django==4.2.10),改用django>=4.2或django~=4.2.0 - 绝不包含间接依赖(比如
urllib3、certifi)——它们应由 pip-compile 自动推导并锁定 - 如果项目分环境,用
requirements-dev.in并以-r requirements.in开头,而非复制粘贴
pip-compile 命令必须启用 --generate-hashes 且指定输出路径
默认行为看似省事,但容易埋坑:
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 不加
--output-file=requirements.txt,它会输出到requirements.txt.txt,CI 脚本里一跑就错 -
--generate-hashes是默认开启的,但如果你用了旧版 pip-tools(--hash=sha256:...,安装时配合--require-hashes才能防篡改 - 别用
--upgrade当日常命令;它会强制升到最新兼容版,破坏稳定性。升级应是有意为之:改完requirements.in后再运行 - 遇到冲突报错(如
Inconsistent dependencies),优先试pip-compile --upgrade-package requests单点升级,比全量重锁更可控
pip install -r requirements.txt 时禁用 --upgrade,且必须校验哈希
生成再严谨,安装一步错,全盘失效:
-
pip install -r requirements.txt --upgrade是最常见线上故障源头——它会让 pip 忽略文件里的所有版本号和哈希,重新走依赖解析,等同于没锁 - 部署命令必须是
pip install --require-hashes -r requirements.txt;缺少--require-hashes,pip 会跳过哈希校验,失去完整性保障 - 容器化部署中,Dockerfile 必须拆成两步:
COPY requirements.txt .+pip install --require-hashes -r requirements.txt,否则缓存可能跳过安装 - 若目标环境已有旧包,先执行
pip install --force-reinstall --no-deps -r requirements.txt清掉主依赖,再补装子依赖,避免残留干扰
跨平台/多 Python 版本依赖需用环境标记,不能靠手动切文件
想让同一份 requirements.in 在 Linux/macOS/Windows 和不同 Python 版本下自动适配,靠人维护多套文件是不可持续的:
- 写
uvloop; platform_system != "Windows",pip-compile 会保留在输出文件中,pip install 时自动跳过 Windows - 写
dataclasses; python_version ,编译后仍带条件,Python 3.9 环境下不会尝试安装 - 不要用
-r base.txt这类 include 语法——pip-tools 对它的解析不稳定,容易漏依赖或重复计算 - 如果项目用
pyproject.toml声明依赖,必须加--config-file=pyproject.toml,否则 pip-compile 默认不读它
确定性不是靠一次 compile 就一劳永逸,而是每次修改 requirements.in 后,重新 compile → 推送新 requirements.txt → 部署时严格按哈希安装。最容易被忽略的其实是最后一步:没人检查 CI 脚本里有没有偷偷加上 --upgrade,或者 Docker 构建时有没有因缓存跳过安装。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










