3、requirements.txt:手动编写、pip freeze生成与版本号规范
说到 Python 项目的依赖管理,requirements.txt 绝对是个绕不开的话题。我刚开始带团队那会儿,经常看到有人直接把项目扔过来,丢一句「你装一下依赖跑起来」。结果呢?一跑就报错,版本冲突能让人崩溃一整天。
说白了,requirements.txt 就是一份「依赖清单」。它告诉别人:我这个项目需要哪些包,以及这些包应该是什么版本。今天我就把这块掰开揉碎了讲清楚。
3.1 手动编写 requirements.txt
手动写这个文件,其实没那么玄乎。就是纯文本,一行一个包名。比如:
flask
requests
numpy
pandas
嗯,这样写确实能跑。但你想想看,这样写有什么问题?
问题大了去了。不加版本号,别人装的时候就会装最新版。万一新版本改了接口,你的代码就炸了。我在项目中遇到过好几次这种坑——本地跑得好好的,部署到服务器上就报错,查了半天发现是某个依赖偷偷升了级。
所以,我个人的习惯是:永远指定版本号。哪怕你写 flask>=2.0,也比什么都不写强。
3.2 使用 pip freeze 生成
手动写太累?那就用工具。最常用的就是 pip freeze。
命令很简单:
pip freeze > requirements.txt
这条命令会把当前环境中所有已安装的包,连同版本号一起导出。我经常在项目开发到一定阶段时跑一下,把当前稳定的依赖锁住。
不过要注意一点:pip freeze 会导出所有包,包括那些间接依赖。举个例子,你装了 flask,它自动装了 click、itsdangerous 这些。这些间接依赖也会被写进去。
这样做的好处是「完整」,坏处是「冗余」。我个人建议:只保留直接依赖,间接依赖交给 pip 自己去解析。但如果你要部署到生产环境,锁死所有版本反而更安全。
pip list --format=freeze 查看更干净的输出格式。
3.3 版本号规范详解
版本号这块,很多人觉得不就是写个数字嘛。其实里面的门道不少。Python 的版本号规范遵循 PEP 440,但日常我们用到的就几种。
我整理了一张表,你一看就明白:
| 符号 | 含义 | 示例 | 说明 |
|---|---|---|---|
== |
精确匹配 | flask==2.0.1 |
必须安装这个确切版本 |
>= |
大于等于 | flask>=2.0 |
允许安装 2.0 及以上任何版本 |
<= |
小于等于 | flask<=2.3 |
不允许超过 2.3 |
~= |
兼容版本 | flask~=2.0 |
允许 2.0.x,不允许 3.0 |
* |
通配符 | flask==2.0.* |
允许 2.0 下的任何补丁版本 |
这里我重点说一下 ~= 和 *,因为很多人搞混。
~= 的意思是「兼容版本发布」。比如 flask~=2.0,它允许安装 2.0.1、2.0.2,但不会装 2.1.0 或 3.0.0。为什么?因为主版本号变了,很可能有破坏性变更。
* 是通配符,flask==2.0.* 等价于 flask>=2.0.0, <2.1.0。说白了就是「锁定主次版本,补丁版本随意」。
* 只能用在最后一位。写 flask==2.*.1 是不合法的。
3.4 实际项目中的最佳实践
讲了这么多理论,来点实际的。我在项目中通常这样写 requirements.txt:
# 核心框架
flask>=2.0, <3.0
flask-sqlalchemy~=3.0
# 数据处理
numpy>=1.21, <2.0
pandas==1.3.5
# 工具库
python-dotenv==0.19.*
requests>=2.25
你看,我混合使用了多种写法。为什么?
- 核心框架:给一个范围,允许小版本升级,但锁死大版本
- 数据处理:精确锁定,因为这些库的 API 变化频繁
- 工具库:宽松一点,只要不出大问题就行
我曾经因为 pandas 从 1.3 升到 1.4 时,某个函数被标记为废弃,导致线上报警。从那以后,对于数据处理类的库,我倾向于精确锁定。
3.5 生成 requirements.txt 的完整流程
最后,我分享一下我常用的工作流:
- 创建虚拟环境:
python -m venv venv - 激活环境:
source venv/bin/activate(Windows 用venv\Scripts\activate) - 安装依赖:
pip install flask pandas ... - 生成文件:
pip freeze > requirements.txt - 手动精简:删掉间接依赖,只保留直接依赖
- 提交版本控制:把
requirements.txt提交到 Git
pip install -r requirements.txt 一键复现环境。
嗯,关于 requirements.txt 的内容就这些。下一章我们会聊到 Pipfile 和 pyproject.toml,那是更现代化的依赖管理方式。但说实话,requirements.txt 依然是目前最通用、最兼容的方案,你值得掌握它。