生产环境必须用 pip-sync requirements.txt 或 poetry install --only main,因 pip install -r 会混装依赖、不清理旧包、引入未声明间接依赖,导致镜像膨胀、版本冲突与运行时错误。

因为混装开发依赖和生产依赖会直接导致容器镜像膨胀、攻击面扩大、静默版本冲突,甚至让 ModuleNotFoundError 报错指向错误包(比如提示缺 pytest,实际是它污染了 click 版本)。
pip install -r requirements.txt 为什么不能用在生产环境
它只做“加法”,不清理旧包,也不校验是否多余。更关键的是:requirements.txt 很可能来自 pip freeze,里面包含大量未声明的间接依赖(如 urllib3、idna),这些包你没主动选过,却会被锁死版本——下次升级 requests 时,urllib3 可能被连带升级,而你的业务代码恰好依赖某个旧版行为,就挂了。
- 开发时用
pip freeze > requirements.txt是偷懒,不是规范 - 生产部署必须用
pip-sync requirements.txt,它会卸载多余包、重装不符版本、确保环境与文件完全一致 - 如果误把
requirements-dev.txt交给pip install -r,ipython、jupyter-client就会悄悄进生产容器,白占 80MB+ 空间
requirements.in 和 requirements-dev.in 怎么写才不踩坑
核心就一条:只写你「主动选择」的顶层包,不写传递依赖,不手写 == 锁死(除非强约束)。
-
requirements.in:只放运行必需的包,例如fastapi>=0.115.0、psycopg2-binary -
requirements-dev.in第一行必须是-r requirements.in,再追加开发工具,例如:pytest==7.4.4、mypy==1.10.0 - 真正锁定版本由
pip-compile输出的.txt文件负责,.in文件只是“需求清单”,保持可读性和可维护性
poetry install --only main 为什么必须显式写
因为默认 poetry install 会把所有组都装上,包括 dev 组里的 mypy、ruff —— 它们不仅不参与运行,还会触发额外编译(比如拉一堆类型 stubs),拖慢构建速度,还可能因间接依赖覆盖生产包路径。
- CI/CD 阶段漏掉
--only main是高频失误,日志里常看到误导性报错,比如ImportError: cannot import name 'AsyncExitStack',实际是anyio被 dev 工具的旧依赖降级了 -
poetry add pytest --group dev才是正确写法;--dev参数已被弃用,留着会警告,未来版本直接报错 - 本地开发想还原干净环境,可以用
poetry install --only main,dev,注意逗号不能有空格
最易被忽略的点是:环境变量或配置文件本身不会自动隔离依赖,依赖隔离靠的是安装阶段的工具选择(pip-sync 或 poetry install --only)和输入文件来源(requirements.txt 还是 requirements-dev.txt)。光靠 ENV=prod 切配置,挡不住 pip install -r requirements-dev.txt 这种硬编码操作。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











