pip-compile必须在激活虚拟环境中运行,因为它需读取当前Python解释器版本、平台信息及已安装构建后端状态,才能正确解析带环境标记的依赖(如uvloop; platform_system != "Windows"),否则可能漏掉条件依赖或锁错版本。

pip-compile 为什么必须在激活的虚拟环境中运行
因为 pip-compile 需要读取当前 Python 解释器的版本、平台信息(如 platform_system)、以及已安装构建后端(如 setuptools、build)的实际状态,才能正确解析带环境标记的依赖,比如:uvloop; platform_system != "Windows" 或 dataclasses; python_version 。如果在系统 Python 或未激活的环境中运行,它可能漏掉条件依赖,或错误地锁死不兼容版本。
常见错误现象:pip-compile 输出的 requirements.txt 里没有预期的条件行,或者 CI 构建时提示 No matching distribution。
- 始终先
source .venv/bin/activate(Linux/macOS)或.venv\Scripts\activate(Windows) - 不要用
pipx run pip-tools pip-compile处理多 Python 版本项目——它默认调用系统python,而非你项目指定的版本 - 跨版本编译时,显式用
python3.9 -m piptools compile或py -3.9 -m piptools compile
requirements.in 怎么写才不会让 pip-compile 锁错依赖
手写 requirements.in 是整个流程最易出错的一环。它不是 pip freeze 的输出,而是你**主动声明的顶层依赖契约**。写错会导致传递依赖被错误收缩、哈希校验失败、甚至引入不兼容子版本。
典型翻车场景:升级 django 后,pip-compile 把 sqlparse 锁到 0.4.4,但该版本与新 Django 的 __all__ 导出不兼容,运行时报 AttributeError。
立即学习“Python免费学习笔记(深入)”;
- 只写你代码里
import过的包,不写间接依赖(如requests自带的urllib3) - 用宽松约束而非硬绑定:
django>=4.2✅,django==4.2.10❌(后者会让升级变手动劳动) - 避免
-r base.txt引用——pip-tools对嵌套-r支持不稳定,容易重复解析或跳过 - 开发/生产分离时,用
requirements-dev.in并以-r requirements.in开头,别把pytest、mypy混进主文件
pip-sync 同步后为什么还有包残留或缺失
pip-sync 默认只管理 requirements.txt 显式列出的包,对“环境里已有但不在清单中”的包保持沉默。这不是 bug,是设计选择——防止误删系统关键包(如 pip、setuptools)。但这也意味着你得主动告诉它“清理”。
常见症状:pip-sync 执行完,pip list 仍显示旧版 click;或 import flask 成功但 flask-sqlalchemy 找不到——后者根本没出现在 requirements.txt 里。
- 加
--delete-missing参数强制卸载未在.txt中声明的包 - 若需控制
pip、wheel等自身依赖,必须在requirements.txt中显式写出,并配--trusted-host处理私有源 - 别指望
pip-sync修复pyproject.toml中的[build-system]依赖——它只管install阶段,不碰构建后端 - CI 中建议加
--no-deps+--force-reinstall组合,避免缓存干扰
生成带哈希的 requirements.txt 要注意什么
哈希校验(--generate-hashes)能防止中间人篡改或镜像源污染,但开启后 pip-compile 行为会变严格:所有依赖必须可解析出确定哈希,且不能含 --find-links 或本地路径。
最容易卡住的地方:某个包在 PyPI 上没有 wheel,只有 sdist,而你的 CI 环境没装 gcc 或 rustc,导致 pip install --require-hashes 直接失败。
- 生成时加
--generate-hashes --index-url https://pypi.org/simple/,避免私有源干扰哈希计算 - 若依赖含 C 扩展(如
numpy、cryptography),确保 CI 使用预编译 wheel 镜像(如https://pypi.org/simple/),而非源码构建 - 哈希文件不可直接编辑——改了任何一行都得重跑
pip-compile,否则pip install --require-hashes拒绝安装 - 本地调试时可先不用哈希,上线前再生成带哈希的正式版
requirements.txt
pip-compile 和 pip-sync 不是黑盒命令,它们的行为高度依赖你当前环境的状态、输入文件的写法、以及是否显式传参。一个没加 --delete-missing 的 pip-sync,和一个在错误 Python 版本下跑的 pip-compile,都会让锁定形同虚设。


















