news 2026/9/29 6:21:07

Hatch 环境锁定文件(pylock.toml)完全指南:配置、生成、同步与升级

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Hatch 环境锁定文件(pylock.toml)完全指南:配置、生成、同步与升级
  • 开发工具
  • 构建工具

【免费下载链接】hatch

Modern, extensible Python project management

项目地址:https://gitcode.com/gh_mirrors/ha/hatch
点击查看免费下载

本篇技术指南聚焦 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),使环境安装的包与锁文件完全一致。前提有两个:

  1. 环境必须配置了locked;
  2. 锁文件必须已存在——先运行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正是验证"锁文件内容过时则检测失败"的端到端测试。

导出锁文件

有两种需要导出而非常规锁定的场景:

  1. 为未配置locked = true的环境生成锁文件;
  2. 将锁文件写到自定义位置。

使用--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

项目地址:https://gitcode.com/gh_mirrors/ha/hatch
点击查看免费下载

相关推荐

上一篇:终极Hazel Engine排坑指南:编译与运行时错误速解方案
下一篇:OpenCore Legacy Patcher终极解析:让旧Mac重获新生的完整技术指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 6:19:18

热管理供应商的全国交付能力:物流与现场支持怎么搭

热管理供应商的全国交付能力&#xff0c;由三块构成&#xff1a;①物流体系——批量件走干线物流区域分拨&#xff0c;交期承诺有冗余&#xff1b;②现场支持——设备安装、调试、培训、故障响应按区域配置&#xff0c;紧急问题远程到场双通道&#xff1b;③备件与返修——备件…

作者头像 李华
网站建设 2026/9/29 6:18:31

音视频修炼之编码器(三):软硬编码对比

软编 vs 硬编完整对比编码用 CPU 还是 GPU/专用芯片? 选错差 10x. 这一篇讲清楚.本文速览章节阅读重点0. 三大编码方式把握本节核心概念和使用场景1. 速度对比按场景做技术取舍2. 画质对比按场景做技术取舍3. 码率压缩率把握本节核心概念和使用场景4. 功耗把握本节核心概念和使…

作者头像 李华
网站建设 2026/9/29 6:18:05

Kimi K2 接入 TaoToken:MoE 思维型模型的工具调用配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华