pip freeze > requirements.txt在生产中危险,因它无差别导出所有已安装包(含dev工具、间接依赖),无法区分真实需求与环境偶然状态;必须用pip-compile从requirements.in解析生成带哈希的锁定文件,并配合--require-hashes部署。

做不到“绝对保证”,但能逼近工程意义上的确定性——关键不在工具链多炫酷,而在约束是否闭环、执行是否不可绕过。
为什么 pip freeze > requirements.txt 在生产中是危险操作
这条命令会把当前环境中所有已安装包(包括你没主动装、但被间接拉进来的 dev 依赖、调试工具、甚至 PyCharm 自带的插件包)全 dump 进去。它不区分“项目真正需要的”和“环境偶然存在的”。
- 常见错误现象:
pip freeze输出里混入了pywin32(Windows-only)、ipython、black等开发期工具,部署到 Linux 生产机时直接报错 - 使用场景:仅适用于“裸环境 + 手动精筛后”的一次性快照,绝不能作为自动化流程的默认步骤
- 根本问题:它反映的是“当前状态”,而非“声明意图”——而生产环境必须基于可审计、可追溯的声明来构建
必须用 pip-tools 的 pip-compile 而不是 pip freeze
pip-compile 强制你从一个明确的输入(requirements.in)出发,通过解析依赖树、解决版本冲突、生成带哈希校验的锁定文件(requirements.txt),把“意图”转为“确定性结果”。
- 实操建议:
- 只在
requirements.in中写你**主动选择**的顶层依赖,例如:django==4.2.15、psycopg2-binary>=2.9.7 - 运行
pip-compile --generate-hashes --allow-unsafe --upgrade,生成带--hash行的requirements.txt - 部署时用
pip install --require-hashes -r requirements.txt,任何包内容变动都会失败
- 只在
- 为什么必须加
--hash:防止中间人篡改 PyPI 包或镜像源缓存污染,这是金融/政务类生产环境的硬性要求 - 注意
--allow-unsafe:某些包(如setuptools)本身被 pip-tools 标记为 unsafe,但实际无法避免,需人工确认并接受
虚拟环境必须与 CI/CD 流水线强绑定,且禁止手动激活
任何允许开发者本地 source venv/bin/activate 后再跑 pip install 的流程,都等于在生产一致性上开了后门。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 正确做法:
- CI 流水线第一步:用
python -m venv .venv创建全新环境 - 第二步:用
.venv/bin/python -m pip install --upgrade pip升级 pip 到已知安全版本(如24.3.1) - 第三步:严格用
.venv/bin/python -m pip install --require-hashes -r requirements.txt
- CI 流水线第一步:用
- 关键细节:所有命令必须显式调用
.venv/bin/python和.venv/bin/pip,禁止依赖PATH或 shell 激活逻辑——后者在非交互式 CI 环境中可能失效 - 容易踩的坑:某些 CI 平台(如 GitLab Runner)默认不加载 shell 配置,
source命令静默失败却继续执行后续步骤,导致你以为在虚拟环境里,其实是在系统 Python 上装包
容器镜像层必须固化依赖安装过程,禁止 runtime 安装
Dockerfile 里出现 RUN pip install -r requirements.txt 是高危行为——它让每次构建都重新解析依赖,哪怕 requirements.txt 没变,pip 的解析器更新或网络抖动都可能导致不同结果。
- 正确写法:
FROM python:3.11-slim COPY requirements.txt . # 强制使用确定性 pip 版本,并禁用缓存干扰 RUN pip install --upgrade "pip==24.3.1" && \ pip install --require-hashes --no-cache-dir -r requirements.txt - 为什么加
--no-cache-dir:避免 pip 缓存中混入旧版本包或损坏的 wheel,确保每次都是干净下载+校验 - 更进一步:把
requirements.txt和其哈希值一起做为构建参数传入,CI 流水线在触发构建前先校验该文件 SHA256 是否与主干分支一致,不一致则拒绝构建
真正难的不是技术动作,而是让所有人放弃“我本地能跑就行”的惯性——所有依赖变更必须经过 requirements.in 提交、CI 自动编译、镜像构建三道关卡,缺一不可。任何跳过其中一环的操作,本质上都在给生产环境埋雷。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










