Poetry pre-commit 钩子完全指南:用 poetry-check、poetry-lock、poetry-export、poetry-install 守护依赖一致性
2026/9/10 20:55:01 网站建设 项目流程

Poetry pre-commit 钩子完全指南:用 poetry-check、poetry-lock、poetry-export、poetry-install 守护依赖一致性

【免费下载链接】poetryPython packaging and dependency management made easy项目地址: https://gitcode.com/GitHub_Trending/po/poetry

pre-commit 是一个用于构建和运行 git hooks 的框架,Poetry 官方提供了poetry-checkpoetry-lockpoetry-exportpoetry-install四个 pre-commit 钩子,帮助你在每次提交、切换分支或合并代码时自动验证pyproject.toml配置、保持poetry.lock最新、同步requirements.txt并确保依赖已安装。读完本文,你将掌握这四个钩子的工作原理、参数配置、monorepo 场景下的目录切换技巧,以及pre-commit autoupdate在 Poetry 下的替代方案,从而把依赖管理的检查固化进团队工作流。

背景:pre-commit 与 Poetry 的集成方式

pre-commit 是一个通用的 git 钩子管理框架,它允许你把任意工具注册为提交前的检查步骤。Poetry 仓库本身通过根目录下的 .pre-commit-hooks.yaml 文件声明了这些钩子,pre-commit 框架会读取该文件来发现可用钩子。从该配置文件可以看到四个钩子的核心定义:

- id: poetry-check name: poetry-check description: run poetry check to validate config entry: poetry check language: python pass_filenames: false files: ^(.*/)?(poetry\.lock|pyproject\.toml)$ - id: poetry-lock name: poetry-lock description: run poetry lock to update lock file entry: poetry lock language: python pass_filenames: false files: ^(.*/)?(poetry\.lock|pyproject\.toml)$ - id: poetry-install name: poetry-install description: run poetry install to install dependencies from the lock file entry: poetry install language: python pass_filenames: false stages: [post-checkout, post-merge] always_run: true

这些定义揭示了几个关键行为:

  • 四个钩子均以language: python运行,pre-commit 会为它们创建独立的隔离环境,无需预先全局安装 Poetry;
  • pass_filenames: false表示钩子不接收文件参数,而是由命令自行处理项目文件;
  • poetry-checkpoetry-lock通过files正则限定了触发条件:仅当poetry.lockpyproject.toml发生变化时才运行;
  • poetry-install则声明了stages: [post-checkout, post-merge],默认挂在post-checkoutpost-merge阶段执行(详见下文专节)。

两个重要默认行为

在配置这些钩子之前,必须先了解两条由 Poetry 官方文档明确给出的规则:

  1. args:会覆盖默认参数:如果你在.pre-commit-config.yaml中为某个钩子指定了args:,那么该钩子的默认参数将被全部覆盖。此时你必须完整地写出所有需要的参数,而不是在默认值基础上追加。
  2. pyproject.toml不在根目录时:可以通过args: ["-C", "./subdirectory"]指定工作目录。-C--directory,是 Poetry 的全局选项,作用是把命令的工作目录切换到指定路径,所有命令行参数都会相对于该目录解析(见 docs/cli.md 中的全局选项说明)。

poetry-check:阻止损坏的配置进入仓库

poetry-check钩子调用poetry check命令,确保 Poetry 配置不会以损坏的状态被提交。

钩子实际校验什么

从 src/poetry/console/commands/check.py 的CheckCommand实现可以看到,poetry check会执行以下校验:

  • 通过Factory.validate()验证pyproject.toml的完整结构(check.py);
  • 校验 trove classifiers(分类器):识别无法识别或已弃用的分类器,并给出替换建议;同时允许Private ::开头的私有分类器(check.py);
  • 校验 README 声明:检查tool.poetry.readmeproject.readme中声明的文件是否真实存在(check.py);
  • 校验依赖声明中引用的 source 是否与已配置的仓库一致(check.py);
  • 校验 lock 文件一致性:检查poetry.lock是否存在,以及pyproject.toml是否发生了显著变化导致 lock 过期(check.py)。

当存在错误时,命令返回码为 1(pre-commit 会把非零返回码视为检查失败),无错误时输出All set!

支持的参数

poetry-check钩子接受与poetry check命令相同的参数,核心选项如下(对应 check.py 中的定义,详见 docs/cli.md):

选项说明
--lock校验当前pyproject.toml对应的poetry.lock是否存在
--strict只要出现 warning 即判定失败(返回码 1)

由于args:会覆盖默认值,如需同时启用两个选项,应显式写出:

repos: - repo: https://github.com/python-poetry/poetry rev: '' # 填写版本号 hooks: - id: poetry-check args: ["--lock", "--strict"]

poetry-lock:确保锁文件与声明同步

poetry-lock钩子调用poetry lock命令,确保每次提交时poetry.lock都与pyproject.toml保持同步。

命令行为

从 src/poetry/console/commands/lock.py 可以看到,LockCommand读取当前目录的pyproject.toml,解析并锁定依赖到poetry.lock;默认情况下,已经在 lock 文件中存在的包不会被更新(lock.py),这与 docs/cli.md 的描述一致。

支持的参数

poetry-lock钩子接受与poetry lock命令相同的参数,核心选项为:

选项说明
--regenerate忽略现有 lock 文件,从零重新生成

通常你希望锁文件既不过期、又不被无谓地刷新,因此默认参数即可满足大部分场景:

repos: - repo: https://github.com/python-poetry/poetry rev: '' # 填写版本号 hooks: - id: poetry-lock

如果依赖声明发生了大规模变更,希望在提交时强制重新生成锁文件,可以显式传入--regenerate

- id: poetry-lock args: ["--regenerate"]

poetry-export:同步 requirements.txt

poetry-export钩子调用poetry export命令,将当前依赖导出同步到requirements.txt

重要前提

  • **该钩子由 Export Poetry Plugin 的说明,该插件自 Poetry 2.0 起不再随 Poetry 默认安装。你需要先安装插件,或者在pyproject.toml中声明项目级插件依赖:
[tool.poetry.requires-plugins] poetry-plugin-export = ">=1.8"
  • 推荐在poetry-export之前先运行poetry-lock钩子,或运行带--lock参数的poetry-check,确保锁文件处于最新状态,导出结果才与项目实际依赖一致。

默认参数与自定义

钩子的默认参数为:

args: ["-f", "requirements.txt", "-o", "requirements.txt"]

即在当前工作目录创建/更新requirements.txt-f指定导出格式,-o指定输出文件)。由于默认值会被args:整体覆盖,自定义时必须完整写出所有参数。

poetry-export钩子同样接受与poetry export命令相同的参数。可在.pre-commit-config.yaml中添加verbose: true,让导出内容输出到控制台以便审查:

hooks: - id: poetry-export args: ["-f", "requirements.txt"] verbose: true

也可以加入--dev参数,把开发依赖一并写入requirements.txt

hooks: - id: poetry-export args: ["--dev", "-f", "requirements.txt", "-o", "requirements.txt"]

poetry-install:锁文件变更后自动安装依赖

poetry-install钩子调用poetry install命令,确保所有被锁定的包都已安装到当前环境中。

与其他钩子的阶段差异

这是四个钩子中最特殊的一个:它默认并不运行在pre-commit阶段,而是运行在post-checkoutpost-merge阶段。原因很直观——当你切换分支或合并代码后,pyproject.toml/poetry.lock的内容可能已发生变化,此时自动执行poetry install能让环境立即与新的锁文件对齐,避免提交时才发现环境过期。

正如 .pre-commit-hooks.yaml 中的定义所示,该钩子带有stages: [post-checkout, post-merge]always_run: true。为了启用它,你有两种安装方式:

  1. .pre-commit-config.yaml中为对应仓库指定default_install_hook_types,让 pre-commit 安装这些阶段的钩子;
  2. 手动执行以下命令安装对应阶段钩子:
pre-commit install --install-hooks -t post-checkout -t post-merge

支持的参数

poetry-install钩子接受与poetry install命令相同的参数,例如排除特定依赖组:

- id: poetry-install args: ["--without", "test,docs"]

其他常用选项(如--with--no-root等)同样可以通过args:传入,详见 docs/cli.md 中关于install命令的说明。

配置示例:从最小化到 monorepo

最小化配置

一个同时启用四个钩子的最小化.pre-commit-config.yaml示例:

repos: - repo: https://github.com/python-poetry/poetry rev: '' # 填写版本号 hooks: - id: poetry-check - id: poetry-lock - id: poetry-export - id: poetry-install

monorepo / 非根目录场景

pyproject.toml不在仓库根目录、或仓库采用 monorepo 结构时,需要为每个钩子显式传入-C参数指定子目录:

repos: - repo: https://github.com/python-poetry/poetry rev: '' # 填写版本号 hooks: - id: poetry-check args: ["-C", "./subdirectory"] - id: poetry-lock args: ["-C", "./subdirectory"] - id: poetry-export args: ["-C", "./subdirectory", "-f", "requirements.txt", "-o", "./subdirectory/requirements.txt"] - id: poetry-install args: ["-C", "./subdirectory"]

注意poetry-export在子目录场景下必须同时调整输出路径-o,否则生成的requirements.txt会落在错误的位置。更多关于 pre-commit 的用法请参考其官方文档。

FAQ:版本更新与替代方案

为什么pre-commit autoupdate不会更新到最新版本?

pre-commit autoupdate会把.pre-commit-config.yaml中每个仓库的rev更新为默认分支上最新的 tag。而 Poetry 采用多分支策略:默认分支是活跃的开发分支,修复会被 backport 到稳定分支,新 tag 都是在这些稳定分支上打出的。

pre-commit 官方明确决定不支持这种分支策略——既不支持用户在配置侧指定查找 tag 的分支,也不支持钩子作者侧声明分支,因此pre-commit autoupdate对本文描述的 Poetry 钩子不可用,它可能把rev更新成非预期的值。

规避方法:使用--repo参数(可重复指定)显式列出需要更新的仓库,从而避免 Poetry 仓库被意外改动:

pre-commit autoupdate --repo https://github.com/python-poetry/poetry

(注意:pre-commit 官方同样明确拒绝实现“显式排除某些仓库”的选项。)

有没有pre-commit autoupdate的替代方案?

可以使用pre-commit-update(一个 PyPI 上的工具)替代pre-commit autoupdate。由于它本身可以作为 pre-commit 钩子使用,最省事的做法是直接把它加进.pre-commit-config.yaml,让仓库版本在每次运行 pre-commit 时被自动检查和更新:

repos: - repo: https://gitlab.com/vojko.pribudic.foss/pre-commit-update rev: v0.5.1post1 hooks: - id: pre-commit-update - repo: https://github.com/python-poetry/poetry rev: 1.8.3 hooks: - id: poetry-check - id: poetry-lock - id: poetry-export - id: poetry-install

这样,每次 pre-commit 钩子运行时,.pre-commit-config.yaml中各个仓库的版本都会被检查并更新。更高级的配置(如自动创建更新 PR、指定忽略的仓库等)请参考pre-commit-update的文档。

总结:四个钩子的选型建议

钩子触发阶段核心作用典型参数
poetry-checkpre-commit校验pyproject.toml结构与 lock 一致性--lock--strict
poetry-lockpre-commit保证poetry.lock与声明同步--regenerate
poetry-exportpre-commit同步导出requirements.txt-f-o--dev
poetry-installpost-checkout / post-merge锁文件变更后自动安装依赖--without--with

工程实践中,建议至少启用poetry-checkpoetry-lock组成最小防线;需要维护requirements.txt兼容工具链时再加poetry-export(记得在它之前运行 lock 类钩子);团队协作频繁切换分支时,启用poetry-install能显著减少"环境与锁文件脱节"带来的问题。所有钩子的底层命令实现均可直接查看本仓库源码:check.py、lock.py,钩子声明见 .pre-commit-hooks.yaml。

【免费下载链接】poetryPython packaging and dependency management made easy项目地址: https://gitcode.com/GitHub_Trending/po/poetry

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询