Python 一直不缺依赖管理工具,真正缺的是一份能跨工具交换的标准锁文件。PEP 751 定义了 pylock.toml,目标是让解析依赖和安装依赖成为两个可以分离的步骤:一个工具生成锁定结果,另一个兼容工具按照相同结果完成安装。
这意味着团队不必因为构建系统、开发环境或部署平台使用不同工具,就维护多份含义相近但格式互不兼容的锁文件。
pylock.toml 解决的不是“版本范围”,而是“安装结果”
普通依赖文件经常只描述允许范围:
httpx>=0.27,<1
rich>=13,<14
这份声明无法保证两次安装得到完全相同的版本。解析器会结合发布时间、Python 版本、操作系统和依赖关系,选择当时可用的候选包。
锁文件承担的是另一项职责:记录解析后的具体软件包、版本、构件及校验信息,使安装工具尽量避免重新求解依赖。标准化后的 pylock.toml 还允许兼容 PEP 751 的工具读取同一份结果,而不必理解某个工具的私有锁文件格式。
需要注意,标准格式不等于跨平台结果会自动出现。锁文件能覆盖哪些 Python 版本、操作系统和 CPU 架构,仍取决于生成命令、输入约束以及解析器能力。只在 Linux 和 Python 3.12 环境中生成并验证的文件,不应未经测试就被视为 Windows、macOS 或其他 Python 版本的可靠部署清单。
从 pip 生成一份标准锁文件
可以这样实践:创建一个空目录,并准备 requirements.in。
mkdir pylock-demo
cd pylock-demo
cat > requirements.in <<'EOF'
httpx>=0.27,<1
rich>=13,<14
EOF
python -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip lock -r requirements.in -o pylock.toml
Windows PowerShell 中激活虚拟环境可改为:
.venv\Scripts\Activate.ps1
这里要区分三类文件:
requirements.in表达项目接受的版本范围,适合人工维护。pylock.toml保存解析后的安装计划,适合提交到版本库。- 虚拟环境是锁文件的实际安装目标,不应提交到版本库。
生成后,可以先检查文件头和被锁定的软件包:
sed -n '1,80p' pylock.toml
pip lock 的可用性和参数取决于本地 pip 版本,因此 CI 中应固定或明确最低 pip 版本,并执行 python -m pip lock --help 验证环境。生成命令也应在受控平台运行,避免开发者机器差异悄悄改变锁定结果。
用 uv 和 PDM 消费同一份锁定结果
PEP 751 的价值不只在于文件名统一,而在于兼容工具能够消费同一份锁定数据。可以在两个全新的虚拟环境中分别验证。
使用 uv 时,可以这样安装:
python -m venv .venv-uv
uv pip install --python .venv-uv/bin/python -r pylock.toml
.venv-uv/bin/python -c "import httpx, rich; print(httpx.__version__)"
Windows 上应把解释器路径替换为 .venv-uv\Scripts\python.exe。
使用支持 PEP 751 的 PDM 版本时,可以这样指定锁文件:
python -m venv .venv-pdm
pdm install --venv .venv-pdm --lockfile pylock.toml
不同版本的 uv 和 PDM 对 pylock.toml 的支持范围及命令参数可能变化。把这些命令加入 CI 前,应先检查当前版本的帮助信息:
uv pip install --help
pdm install --help
跨工具测试的重点不是“命令返回了零”,而是确认工具没有重新解析出另一套版本。可以记录安装结果并进行比较:
uv pip freeze --python .venv-uv/bin/python | sort > uv-installed.txt
pdm run python -m pip freeze | sort > pdm-installed.txt
diff -u uv-installed.txt pdm-installed.txt
这段比较命令假设 PDM 当前运行环境就是刚才安装依赖的环境;如果项目配置不同,应显式激活目标虚拟环境后再执行 python -m pip freeze。
CI 中把“生成”和“验证”分开
锁文件应由明确的更新流程生成,而普通构建只负责验证和安装。一个可改造的 CI 脚本如下:
#!/usr/bin/env bash
set -euo pipefail
python -m venv .ci-venv
python -m pip install --python .ci-venv/bin/python \
--upgrade pip uv
uv pip install --python .ci-venv/bin/python -r pylock.toml
.ci-venv/bin/python -c "import httpx, rich"
更新依赖时,再单独运行:
python -m pip lock -r requirements.in -o pylock.toml
git diff -- pylock.toml
审查锁文件变化时,至少要关注新增和删除的软件包、版本跳跃、来源变化以及构件哈希变化。锁文件能够提高可复现性,但不能替代漏洞扫描、来源控制和制品签名验证。
采用前的检查清单
在团队中引入 pylock.toml,建议确认以下事项:
- 生成端和安装端使用的工具版本都明确支持 PEP 751。
- 锁文件覆盖生产环境所需的 Python 版本和目标平台。
- CI 从干净环境安装,避免缓存或预装包掩盖问题。
- 常规构建只消费锁文件,不在安装阶段静默更新它。
- 依赖升级通过独立变更提交,并审查版本、来源和哈希差异。
- 在 pip、uv、PDM 等实际使用的工具之间执行至少一次交叉安装测试。
PEP 751 并不会消除各工具在解析策略、缓存、工作区管理和发布流程上的差异。它提供的是一条稳定的交换边界:团队可以选择适合自己的解析器和安装器,同时用 pylock.toml 传递一份可审计的依赖安装结果。