pip-compile和pip-sync必须配合使用才能实现确定性依赖管理:pip-compile从requirements.in求解并生成精确锁定文件,pip-sync据此严格同步环境,缺一不可。

能,但必须分两步走:先用 pip-compile 生成锁定文件,再用 pip-sync 严格同步环境 —— 少一步都不算“确定性”。
为什么直接 pip install requirements.in 不行
因为 requirements.in 是高层声明(比如 django>=4.2),pip 每次解析时可能选不同子版本,尤其当网络、缓存、pip 版本或 Python 环境不同时,pip install -r requirements.in 会得到不可复现的结果。这不是 bug,是 pip 的默认行为:它只保证满足约束,不保证结果一致。
常见错误现象:
- 本地
pip install -r requirements.in装完能跑,CI 上却报AttributeError: module 'pydantic' has no attribute 'BaseModel' - 同事重装后
requests变成 2.32.x,而你的是 2.31.0,结果 mock 行为不一致
根本原因:没经过版本求解锁定,依赖图每次都在 runtime 动态生成。
pip-compile 必须手动维护 requirements.in
别用 pip freeze > requirements.in —— 这会把所有间接依赖(如 charset-normalizer、idna)全塞进去,导致 pip-compile 失去“高层抽象”能力,后续升级、审计、分环境都变困难。
正确做法:
- 只写你代码里
import了的包,例如:requests、fastapi、sqlalchemy>=2.0 - 用兼容性符号:
~=比>=更安全(如click~=8.1表示允许 8.1.x,但不升到 8.2) - 避免写死版本(如
django==4.2.10),除非你明确需要某次 patch 修复 - 分环境时,用
requirements-dev.in和-r base.in,但注意:pip-tools 对嵌套-r解析不稳定,建议升级到 ≥7.3.0 并加--resolver=backtracking
pip-sync 不清理旧包是默认行为
pip-sync requirements.txt 默认只管“txt 里有的”,不会卸载当前环境里多出来的包。这是最常被忽略的坑 —— 你以为重装了,其实旧版 tensorflow 还在那儿占着 namespace。
关键参数:
- 加
--delete-missing才会删掉requirements.txt里没有的包 - 加
--trusted-host pypi.org --index-url https://pypi.tuna.tsinghua.edu.cn/simple处理私有源或国内镜像 - Windows 上若
requirements.txt含平台标记(如; platform_system == "Linux"),pip-sync会跳过它们,导致缺失 —— 建议编译时用对应系统,或显式加--python-executable
性能影响:首次运行 pip-sync --delete-missing 可能较慢,因为它要逐个比对已安装包和锁定文件;但这是必要开销 —— 确定性不是免费的。
pyproject.toml 项目要显式告诉 pip-compile
如果你用 pyproject.toml 定义依赖(推荐),pip-compile 默认不读它,除非你明确指定:
pip-compile --config-settings editable-verbose=true pyproject.toml- 或更稳妥:用
[build-system]中的requires+build-backend配置,并确认 pip-tools ≥7.3.0
否则它会回退到找 setup.py 或报错 No requirements file found,而不是静默忽略你的 pyproject.toml。
容易被忽略的一点:pip-compile 的解析结果高度依赖当前虚拟环境的 Python 版本和平台标记。你在 Python 3.11 编译出的 requirements.txt,拿去 3.9 环境里 pip-sync,可能因 environment markers(如 ; python_version >= "3.10")漏装关键包 —— 编译和同步必须在目标环境里做。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











