Python 项目长期缺少一种跨工具的标准锁文件:requirements.txt 能固定版本,却难以完整表达依赖来源、哈希、环境标记和多平台候选包;Poetry、PDM、uv 等工具的专用锁文件又不能自然互换。PEP 751 引入标准化的 pylock.toml,目标是让生成锁文件与安装依赖不再绑定同一个工具。
requirements.txt 为什么不等于标准锁文件
典型的 requirements.txt 看起来很明确:
fastapi==0.115.12
uvicorn==0.34.2
但它本质上仍是一份 pip 风格的安装输入。即使加入哈希和环境标记,不同工具对文件内容、生成方式和扩展语法的理解也可能不同。
pylock.toml 则拥有标准化的数据结构,可以描述锁定的软件包、版本、制品、哈希、依赖关系以及适用环境。更重要的是,它把两个动作拆开了:
- 锁定工具负责解析依赖并生成
pylock.toml。 - 安装工具读取同一文件,选择与当前平台和 Python 环境匹配的制品。
- CI、容器构建和本地开发可以使用不同工具,但共享同一份依赖决策。
这里的“工具无关”并不表示所有工具会产生完全相同的解析结果,而是表示它们可以围绕同一种交换格式协作。
用 pip 或 uv 生成锁文件
下面是一套可以这样实践的最小项目。工具版本需要已经支持 PEP 751;如果现有环境中的命令无法识别 pylock.toml,应先升级对应工具。
创建 pyproject.toml:
[project]
name = "lock-demo"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"httpx>=0.27,<1",
"rich>=13,<15",
]
使用较新的 pip 生成锁文件:
python -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip lock . -o pylock.toml
也可以让 uv 根据同一个项目元数据生成 PEP 751 锁文件:
uv pip compile pyproject.toml -o pylock.toml
不同版本的工具可能调整参数名称,因此应在自动化脚本中固定 pip 或 uv 的版本,并通过下面的命令核对当前版本支持的选项:
python -m pip lock --help
uv pip compile --help
生成后,应把 pylock.toml 提交到版本库。修改 pyproject.toml 中的直接依赖时,重新生成锁文件,并在代码审查中同时检查这两个文件。
用另一种工具安装同一份锁定结果
标准格式真正有价值的地方,不是文件扩展名发生变化,而是安装端可以换工具。使用支持 PEP 751 的 uv,可以这样同步环境:
uv venv
uv pip sync pylock.toml
在采用 PDM 的项目中,可以这样实践:
pdm install --lockfile pylock.toml
运行前应使用 pdm install --help 确认所安装版本已经提供 PEP 751 锁文件支持。团队还应在 CI 中验证安装过程,避免开发机上的新版本工具生成了构建环境尚不能读取的字段。
一个简化的 CI 检查可以写成:
name: locked-dependencies
on:
pull_request:
push:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
with:
version: "0.7.x"
- run: uv venv
- run: uv pip sync pylock.toml
- run: uv run python -c "import httpx, rich; print(httpx.__version__)"
请把示例中的 uv 版本改成团队验证过、明确支持所用 pylock.toml 结构的版本。生产项目还应执行完整测试,而不只是导入包。
迁移时不要直接删除 requirements.txt
从 requirements.txt 迁移可以分阶段完成:
- 把顶层依赖移入
pyproject.toml,明确 Python 版本范围。 - 使用固定版本的锁定工具生成
pylock.toml。 - 在 CI 和容器构建中验证全新环境安装,而不是复用已有虚拟环境。
- 检查 Linux、macOS、Windows 或不同 CPU 架构是否需要不同锁文件。
- 等部署平台、扫描器和内部镜像流程都能读取新格式后,再移除旧文件。
PEP 751 允许采用 pylock.<name>.toml 形式,因此无法用一个锁文件覆盖全部目标环境时,可以维护用途明确的文件,例如 pylock.linux.toml 和 pylock.docs.toml。代价是更新工作增加,团队必须清楚每个文件对应的 Python 版本、平台和部署场景。
采用前的工程检查
pylock.toml 解决的是锁文件交换格式,不会自动解决所有供应链问题。落地时仍需确认以下事项:
- 固定生成锁文件的工具版本,避免解析器升级造成大面积无关变更。
- 在代码审查中检查版本变化、下载来源和哈希,而不是把锁文件当作不可读产物。
- 使用全新环境测试安装,确保没有依赖本地缓存或未声明的软件包。
- 明确锁文件覆盖的平台和 Python 版本;跨平台项目要验证条件依赖与二进制 wheel。
- 保留依赖更新机器人、安全扫描和定期重锁流程。
对新项目,可以直接把 pyproject.toml 与 pylock.toml 作为依赖管理入口。对已有项目,更稳妥的做法是让新旧流程并行一段时间,等 CI、部署和安全工具全部通过验证后,再让 requirements.txt 退出主流程。