最轻量、最可控、也最容易被 ci/cd 接入的方式是用 requirements.in + pip-compile 分层生成不同环境的锁定文件,因其实现声明与锁定分离、支持环境标记、哈希校验、自动依赖解析及 pip-sync 精确同步。

因为不锁定会导致部署失败、行为漂移、安全漏洞无法追溯——不是“可能出问题”,而是“迟早出问题”。
pip install -r requirements.txt 为什么会装出不同版本?
默认情况下,pip 只按 requirements.txt 中的约束解析,而不会强制拒绝更高版本。比如你写的是 requests>=2.25.0,某次 CI 构建时 pip 拉到了 requests==2.32.0,下一次可能是 2.33.1。这两个版本之间可能有:HTTP/2 默认启用、Session.close() 行为变更、或某个已知 CVE 的修复/引入。
- Python minor 版本差异(如 3.11.8 vs 3.11.9)会影响依赖兼容性判断
- PyPI 上包的
requires-python元数据更新后,pip 可能跳过旧版、选新解 - 本地缓存或镜像源不同步,导致解析结果不一致
requirements.in 和 requirements.txt 必须分离
把宽松约束写进 requirements.in(人维护),把精确版本+哈希写进 requirements.txt(机器生成),是避免协作混乱的底线。直接编辑 requirements.txt 等于绕过依赖解析器——下次运行 pip-compile 时,你的手动修改会被覆盖,或触发 IncompatibleRequirements 错误。
-
requirements.in示例:django~=4.2、fastapi>=0.104.0 -
requirements.txt必须包含--hash行,否则无法校验完整性 - CI 流程中应校验
pip-compile输出是否与 Git 中的requirements.txt完全一致,不一致则拒绝合并
锁定文件不是“生成一次就完事”
生产环境的锁定文件必须随 Python 版本、关键依赖升级、安全通告同步更新。比如 urllib3 在 2026 年 4 月曝出 CVE-2026-12345,影响所有 版本,此时仅靠 <code>pip install -U requests 不够——requests 的新版本可能还没带修复后的 urllib3,必须让 pip-compile 重新计算整个依赖树。
- 定期运行
pip-compile --upgrade --upgrade-package urllib3 requirements.in - CI 中加入
pip-check或safety check -r requirements.txt扫描已知漏洞 - 锁定文件要和
pyproject.toml中的requires-python字段对齐,避免跨 Python 版本误锁
真正容易被忽略的是:锁定本身不解决冲突,只暴露冲突。当你发现 pip-compile 报错“no solution found”,说明顶层约束已矛盾——这时得回退、拆分约束、或 pin 某个中间包,而不是强行删掉报错继续跑。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











