- 开发工具
- 构建工具
【免费下载链接】hatch
Modern, extensible Python project management
本篇技术指南聚焦 Hatch 的锁文件(lockfile)能力:Hatch 可以基于 PEP 751 为每个环境生成pylock.toml锁定文件,记录所有依赖的精确解析版本与哈希值,从而在不同机器和 CI 流水线上实现可复现的安装。读完本文,你将掌握锁定环境的配置方式(locked/lock-envs)、三大锁定命令(hatch env lock、hatch dep lock、hatch lock)的完整用法、从锁文件同步环境(hatch dep sync)、自动锁定、依赖升级、同步校验与自定义导出等全部实战操作,并了解内置 pip / uv 两种 locker 的底层实现原理。
为什么需要锁文件
常规的依赖声明(如pyproject.toml中的dependencies)只描述版本约束区间,例如pytest>=7。不同的机器在不同的时间点解析,可能得到不同的具体版本,导致"在我机器上能跑"的经典问题。锁文件则把每个依赖的精确版本和哈希固化下来,保证:
- 任何机器、任何时间安装结果一致(可复现安装);
- CI 与本地开发环境使用同一组依赖版本;
- 依赖被供应链篡改或上游意外发布坏版本时,哈希校验能及时发现。
Hatch 生成的锁文件遵循 PEP 751:由于 PEP 751 规定文件名只允许一个点,环境名中的.会被替换为-。
配置需要锁定的环境
锁文件不是对所有环境默认开启的。你需要先在配置中显式声明哪些环境需要锁定。
按环境开启:locked = true
在环境配置中设置locked = true,Hatch 就会在创建环境或依赖变化时自动维护该环境的锁文件:
[tool.hatch.envs.test] locked = true dependencies = [ "pytest", ]全局开启:lock-envs
如果希望所有环境默认都锁定,可以在[tool.hatch]顶层设置lock-envs = true。它相当于每个环境locked选项的默认值(单个环境locked的默认值是false,除非被lock-envs覆盖),详见 环境配置—Locking 小节。
[tool.hatch] lock-envs = true全局开启后单独退出
lock-envs = true并不强制所有环境锁定,个别环境仍可通过显式locked = false退出:
[tool.hatch] lock-envs = true [tool.hatch.envs.docs] locked = false生成锁文件
hatch env lock:锁定全部或指定环境
不带参数执行时,hatch env lock会为所有配置了locked = true的环境生成锁文件:
$ hatch env lock Locking environment: default Wrote lockfile: /path/to/project/pylock.toml Locking environment: test Wrote lockfile: /path/to/project/pylock.test.toml也可以按名称锁定单个环境:
$ hatch env lock test Locking environment: test Wrote lockfile: /path/to/project/pylock.test.toml注意:按名称锁定单个环境时,该环境必须已配置
locked = true。若想为未配置为 locked 的环境生成锁文件,请使用--export标志。
命名规则:default环境产出pylock.toml,其余环境产出pylock.<ENV_NAME>.toml,遵循 PEP 751 命名约定。矩阵环境(matrix)和其他命名同样按 Hatch 的环境展开机制处理,参见run_lock_workflow中expand_environments与矩阵展开逻辑(tests/cli/env/test_lock.py 有矩阵锁定测试)。
hatch dep lock与hatch lock:锁定当前活动环境
对于通过-e/HATCH_ENV选中的环境(参见 CLI 说明),可以使用:
hatch dep lock—— 与env lock共享相同的解析器选项(--upgrade、--upgrade-package、--export、--export-all、--check);hatch lock——hatch dep lock的简写形式。
从源码看,顶层 hatch lock 与 hatch dep lock 都直接调用同一个run_dep_lock工作流,共享dependency_lock_click_options定义的选项集合(src/hatch/cli/env/lock.py):
click.option("--upgrade", "-U", is_flag=True, help="Upgrade all packages") click.option("--upgrade-package", "-P", multiple=True, help="Upgrade specific package(s)") click.option("--export", "export_path", type=click.Path(), default=None, help="Export lockfile to a custom path") click.option("--export-all", "export_all_path", type=click.Path(), default=None, help="Export lockfiles for all environments to a directory") click.option("--check", is_flag=True, help="Check if lockfile is up-to-date")--export-all会把所有已配置环境锁定到指定目录,行为与hatch env lock --export-all一致。注意在run_dep_lock中,--export与--export-all同时给出会直接报错中止(src/hatch/cli/env/lock.py)。
从锁文件同步环境
hatch dep sync会对活动环境执行所选 locker 的apply_lock步骤(例如使用 UV locker 时执行uv pip sync),使环境安装的包与锁文件完全一致。前提有两个:
- 环境必须配置了
locked; - 锁文件必须已存在——先运行
hatch dep lock或hatch env lock生成。
如果违反上述前提,命令会直接中止。源码中 dep sync 命令 的实现清晰地体现了这一点:环境未locked时提示 "The active environment is notlocked...",锁文件不存在时提示 "No lockfile at ..."。
底层流程为:dep sync→environment.sync_dependencies()→apply_lock_with_locker→ 所选 locker 类的apply_lock(见 apply_lockfile_to_environment)。
自动锁定
配置了locked = true的环境,在hatch env create或hatch run时会自动生成锁文件,触发条件为:
- 锁文件尚不存在;
- 环境的依赖发生了变化。
这套机制确保你在日常开发中无需手动维护锁文件——一旦依赖声明变动,下一次运行就会自动重新解析并更新锁。判断"环境是否有可锁定的输入"由environment_has_lock_inputs(src/hatch/env/lock.py)完成:环境依赖、附加依赖、feature/dependency-groups、项目安装项等任一存在即有内容可锁;若没有任何可锁输入,自动锁定会跳过生成。
升级锁定的依赖
锁文件固定了版本,但依赖可以升级——这由解析器的--upgrade系列选项控制:
升级所有包到其允许范围内的最新版本:
$ hatch env lock test --upgrade只升级指定包(可重复指定):
$ hatch env lock test --upgrade-package requests --upgrade-package urllib3对应选项在底层会透传给解析器:pip locker 将其映射为pip lock --upgrade / --upgrade-package(src/hatch/env/lockers/pip.py),uv locker 则映射为uv pip compile --upgrade / --upgrade-package(src/hatch/env/lockers/uv.py)。
检查锁文件是否最新
在hatch env lock、hatch dep lock或hatch lock上使用--check,可以验证锁文件与当前依赖输入是否同步(重新解析并与现有文件对比)。如果该环境没有任何可锁内容,--check只检查文件是否存在——这正是lockfile_in_sync中state is None时return output_path.is_file()的逻辑(src/hatch/env/lock.py)。
$ hatch env lock test --check Lockfile is up to date: /path/to/project/pylock.test.toml这个选项在 CI 中尤其有用:确保锁文件已被提交入库,并且与pyproject.toml/ 环境依赖保持一致,防止有人绕过锁文件直接改了依赖声明。底层的"对比"方式是先在临时目录重新生成一份锁文件,再与现有文件逐字节比较(pip 与 uv 的in_sync实现均如此,见 src/hatch/env/lockers/pip.py 与 src/hatch/env/lockers/uv.py);tests/cli/env/test_lock.py 中的test_check_lockfile_stale正是验证"锁文件内容过时则检测失败"的端到端测试。
导出锁文件
有两种需要导出而非常规锁定的场景:
- 为未配置
locked = true的环境生成锁文件; - 将锁文件写到自定义位置。
使用--export指定输出路径:
$ hatch env lock default --export locks/default.lock使用--export-all把所有环境的锁文件导出到一个目录:
$ hatch env lock --export-all locks/注意:
--export与--export-all互斥,不能同时使用。
另外,按名称锁定环境时必须配置locked = true的限制,在--export场景下同样放宽:源码中run_lock_workflow只有在"未使用 export 且未配置 locked"时才中止(src/hatch/cli/env/lock.py)。
自定义锁文件名
任何环境都可以用lock-filename选项覆盖默认文件名:
[tool.hatch.envs.test] lock-filename = "requirements-test.lock"该选项支持上下文格式化——resolve_lockfile_path会先应用环境上下文再解析路径,因此可以使用{env_name}、{matrix:...}等占位符(src/hatch/env/lock.py)。例如配置lock-filename = "locks/{env_name}/pylock.toml"会把锁文件分散到按环境命名的子目录(tests/cli/env/test_lock.py 中有对应测试)。
多个环境共享同一锁文件
当多个矩阵环境共享同一个lock-filename时,Hatch 会合并它们的依赖并只生成一次锁文件。合并逻辑在merge_environment_lock_inputs(src/hatch/env/lock.py):
- 单环境时直接使用该环境自身配置;
- 多环境时去重合并全部依赖、union 所有 features 与 dependency-groups;
- 不同 Python 版本的环境共享同一锁文件是非法的:
python配置不一致时会直接中止并提示 "A single lockfile cannot be valid across different Python versions. Use distinctlock-filenamevalues",对应测试见 test_lock_groups_with_different_python_versions_abort; - 使用 UV 且项目存在
pyproject.toml且任一环境需要安装项目时,采用分层合并(layered merge)。
安装器集成与 locker 选择
锁文件的实际生成与应用由locker插件完成。默认情况下,Hatch 会根据环境的安装器自动选择一个内置 locker:
| locker 名称 | 默认选用场景 | 生成命令 | 说明 |
|---|---|---|---|
pip | 默认(非 UV 安装器) | pip lock | 要求 pip 25.1+;仅支持扁平依赖列表,不支持 extras/dependency-groups 分层锁定;apply_lock尚未实现(见下文) |
uv | 虚拟环境 + UV 安装器 | uv pip compile(带哈希)+uv pip sync(应用锁) | 支持分层锁定:extras、dependency-groups、pyproject.toml |
选择逻辑见get_locker_plugin_class(src/hatch/env/lock.py):优先取环境级locker配置,其次取全局tool.hatch.locker,都未设置时按"UV 安装器选uv,否则选pip"推断。
可以通过配置覆盖默认选择。全局默认:
[tool.hatch] locker = "uv"按环境覆盖(优先于全局):
[tool.hatch.envs.docs] locker = "pip"完整的插件接口定义在 LockerInterface,每个 locker 需要实现三个核心抽象方法:
generate:根据 PEP 508 依赖行(可选带 extras/groups 分层输入)解析并写出锁文件;in_sync:判断现有锁文件是否与当前依赖输入匹配(重新生成后逐字节对比);apply_lock:按锁文件安装包,使环境与锁文件一致。
自定义 locker 通过hatch_register_locker钩子注册,详见 依赖锁定插件文档 中的注册示例与插件发现机制。
pip locker 的限制
需要特别注意:内置piplocker 目前没有实现apply_lock,其实现直接抛出LockerUnsupportedError并提示使用 UV(src/hatch/env/lockers/pip.py)。因此:
- 生成锁文件:pip(
pip lock)与 uv 都可以; - 从锁文件同步安装(
dep sync/ 锁定环境的安装):目前必须使用 uv locker(将安装器设为"uv"或显式locker = "uv")。
此外 pip locker 不支持分层锁定——传入 extras 或 dependency-groups 会直接报错 "The pip locker does not support layered locks with extras or dependency-groups; use installer uv"(src/hatch/env/lockers/pip.py)。相关行为也有测试覆盖:test_dep_sync_aborts_without_lockfile与 pip locker 的 unsupported 报错(tests/cli/dep/test_dep_lock.py)。
uv locker 的生成细节
UV locker 的generate最终拼装出类似下面的命令(src/hatch/env/lockers/uv.py):
uv pip compile <requirements文件> [pyproject.toml] \ --generate-hashes --no-header --output-file <输出路径> \ [--extra <extras>]... [--group <groups>]... \ [--upgrade] [--upgrade-package <pkg>]... \ [--python-version <版本>]值得注意的细节:
- 始终生成哈希(
--generate-hashes)并去除头部注释(--no-header),保证锁文件内容稳定、可校验; - 分层锁定(layered)时,除依赖文件外还会把
pyproject.toml作为编译输入,并通过--extra/--group纳入项目 extras 与依赖组; - 环境配置了
python时,会追加--python-version,确保解析结果针对目标 Python 版本; apply_lock使用uv pip sync(src/hatch/env/lockers/uv.py),并且install_matches_lock通过uv pip sync --dry-run判断环境是否已经与锁文件一致(src/hatch/env/lockers/uv.py),用于锁定环境下跳过不必要的重复安装。
端到端验证与测试覆盖
仓库的测试为上述功能提供了完整的端到端验证,可以作为深入学习的入口:
- tests/cli/env/test_lock.py:覆盖锁文件命名与写入位置、
--check过期检测、--export/--export-all、矩阵环境锁定、共享lock-filename的合并生成与 Python 版本冲突中止、环境依赖被实际编译进锁文件(test_lockfile_records_some_env_dependencies)、Git 修订号被固定(test_lockfile_resolves_git_revision_pin)等; - tests/cli/dep/test_dep_lock.py:覆盖
dep lock/dep sync的报错路径(未锁定环境、锁文件缺失、pip locker 不支持 apply_lock)。
如果你正在为项目引入可复现的依赖管理,推荐的落地顺序是:先在[tool.hatch.envs]中为关键环境设置locked = true(或全局lock-envs = true),运行hatch env lock生成锁文件并提交到版本库,在 CI 中通过hatch env lock --check确保锁文件始终与依赖声明同步;如果需要从锁文件精确还原环境(例如部署或流水线),将对应环境配置为 UV 安装器并使用hatch dep sync。
- 开发工具
- 构建工具
【免费下载链接】hatch
Modern, extensible Python project management
相关推荐
Hatch 依赖锁定(Locker)插件开发与配置完整指南:基于 PEP 751 的 pylock.toml 生成、校验与同步
Hatch 依赖锁定(Locker)插件开发与配置完整指南:基于 PEP 751 的 pylock.toml 生成、校验与同步 本指南围绕 Hatch 的 lo
开发工具构建工具Argo CD v2.10 升级至 v2.11 完全指南:initiatedBy 操作溯源、Redis Egress 网络策略与新健康检查
Argo CD v2.10 升级至 v2.11 完全指南:initiatedBy 操作溯源、Redis Egress 网络策略与新健康检查 本篇升级指南以 Ar
开发工具构建工具Hatch v1.17.0 实战:PEP 751 锁文件(pylock.toml)与统一质量检查命令 hatch check
Hatch v1.17.0 实战:PEP 751 锁文件(pylock.toml)与统一质量检查命令 hatch check 本文围绕 Hatch v1.17.
开发工具构建工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考