有人问:requirements.txt 我写了啊,为什么部署还是报错?这问题太经典了。
requirements.txt 是个好东西,但它只管装什么,不管装哪个版本。
你写 requests,同事装了 2.28,你装了 2.31,接口参数变了,代码就崩了。更狠的是,有些依赖依赖别的依赖,层层嵌套下来,版本冲突根本查不出来。
这就是依赖管理要解决的事:不光知道装什么,还要锁死精确版本,确保任何人在任何时间装出来的东西一模一样。
requirements.txt的问题
看看大多数人怎么写 requirements.txt:
虽然能跑,但同时埋了三个雷:
第一,没有版本号。 pip 默认装最新版,而最新版可能已经 deprecate 了你用的 API。去年还能跑的代码,今天 pip install 就报错。
第二,没有依赖树。 你装了 A 和 B,A 依赖 requests>=2.0,B 依赖 requests<2.28,两个冲突了你根本不知道,直到运行时才炸。
第三,子依赖不确定。 requests 本身又依赖 urllib3 和 certifi,这些子依赖的版本你完全没控制,换台机器可能装出不同版本。
poetry:Python 依赖管理的正解
poetry 做的事很简单:一个 pyproject.toml 管所有配置,一个 poetry.lock 锁死所有依赖的精确版本。
先装 poetry:
在项目根目录初始化:
它会问你一系列问题,大部分直接回车就行,生成的 pyproject.toml 长这样:
[tool.poetry]name = "my-project"version = "0.1.0"description = ""authors = ["你的名字 <you@example.com>"][tool.poetry.dependencies]python = "^3.10"requests = "^2.31"pandas = "^2.0"
^2.31 的意思是:兼容 2.31 到 3.0 之间所有版本,但不包括 3.0。这比你手动写 requests>=2.31,<3.0 优雅多了,而且语义明确。
然后执行:
poetry lockpoetry install
poetry lock 会解析整个依赖树,生成 poetry.lock 文件。这个文件是文本文件,必须提交到git。它精确记录了每一个依赖(包括子依赖)的版本号和下载地址。
别人拿到你的代码后,只要执行 poetry install,poetry 会严格按照 lock 文件安装,保证环境一致。
什么时候该用poetry
不是所有项目都需要 poetry。判断标准很简单:
个人脚本、一次性工具,requirements.txt 写死版本号就够了:
多人协作、要上线的项目,用 poetry。因为:
• 多人环境一致性,不再出现我这能跑你那不行
• 依赖冲突在安装阶段就报错,不会等到运行时
• poetry.lock 提交到 git,部署环境可复现
• pyproject.toml 是 Python 官方推荐的项目元数据格式
新手常见坑
poetry install报错说某个包找不到?
大概率是 Python 版本不匹配。poetry 对 Python 版本要求严格,pyproject.toml 里写的 python = "^3.10" 就是硬性要求。先用 python --version 确认当前版本。
lock文件要不要提交到git?
必须提交。lock 文件是环境复现的关键,不提交等于白锁。
已经用了requirements.txt,怎么迁移?
poetry 支持从 requirements.txt 导入:
poetry add $(cat requirements.txt)
但这只是把依赖加到 pyproject.toml,版本号需要你自己补全。建议逐步迁移,新项目直接用 poetry。
下一篇预告
依赖搞定了,下个项目目录结构该长什么样?10 行代码和 1000 行代码的目录差别在哪?
我是鲁叶的Python,10年互联网古法程序员。
Python/ML/DL/大模型都折腾过,坑也踩了不少。
关注我,持续输出实用干货。