You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Click中为组操作设置升级检查豁免装饰器

解决Click命令组默认执行升级检查、部分命令豁免的问题

你的代码失效的核心原因是Click的执行顺序问题:组的回调函数(common)会在命令的任何回调逻辑之前运行。你原来的bypass_upgrade_check装饰器是在命令执行时才修改state,但这时候common里的check_upgrade()已经跑完了,自然起不到跳过的作用。

下面给你两种可行的实现方案,都能实现「默认检查、标记豁免」的需求,不需要开发者手动添加检查逻辑:

方案一:给命令添加豁免标记(最简洁)

我们可以给需要跳过检查的命令函数添加一个自定义属性,然后在组的回调里直接判断当前命令是否带有这个标记:

import click

def check_upgrade():
    print("执行升级检查...")

class State(object):
    def __init__(self):
        pass

pass_state = click.make_pass_decorator(State, ensure=True)

# 自定义装饰器:给命令函数打上豁免标记
def bypass_upgrade_check(func):
    func._skip_upgrade_check = True
    return func

@click.group()
@pass_state
def common(state, ctx):
    # 获取当前正在执行的命令,检查其回调是否有豁免标记
    if not getattr(ctx.command.callback, "_skip_upgrade_check", False):
        check_upgrade()

@common.command()
def cmd1():
    print("运行命令cmd1")

@bypass_upgrade_check
@common.command()
def cmd2():
    print("运行命令cmd2(跳过升级检查)")

if __name__ == "__main__":
    common()

原理说明

  • 注册命令时,@bypass_upgrade_check会给命令的回调函数添加一个_skip_upgrade_check属性。
  • 组的回调common执行时,通过ctx.command拿到当前执行的命令,直接检查其回调函数的标记,这样判断逻辑在检查之前执行,完全符合需求。

方案二:自定义命令类(适合复杂场景)

如果你的需求后续有扩展(比如需要在豁免时执行其他逻辑),可以通过自定义Click命令类,提前修改状态:

import click

def check_upgrade():
    print("执行升级检查...")

class State(object):
    def __init__(self):
        self.bypass_upgrade_check = False

pass_state = click.make_pass_decorator(State, ensure=True)

# 自定义命令类:在命令执行前修改状态
class BypassUpgradeCommand(click.Command):
    def invoke(self, ctx):
        # 提前拿到State并设置豁免标记
        state = ctx.ensure_object(State)
        state.bypass_upgrade_check = True
        # 执行原命令逻辑
        return super().invoke(ctx)

def bypass_upgrade_check(func):
    # 用自定义命令类包装目标函数
    return click.command(cls=BypassUpgradeCommand)(func)

@click.group()
@pass_state
def common(state):
    if not state.bypass_upgrade_check:
        check_upgrade()

@common.command()
def cmd1():
    print("运行命令cmd1")

# 用自定义装饰器创建命令,再添加到组中
@bypass_upgrade_check
def cmd2():
    print("运行命令cmd2(跳过升级检查)")
common.add_command(cmd2)

if __name__ == "__main__":
    common()

原理说明

  • 自定义的BypassUpgradeCommand重写了invoke方法,在执行命令核心逻辑前就修改了State的属性。
  • 组的回调common执行时,state.bypass_upgrade_check已经被设置为True,因此会跳过检查。

这两种方案都不需要开发者在每个命令里手动添加检查逻辑,只需要给豁免的命令加上@bypass_upgrade_check装饰器即可。

内容的提问来源于stack exchange,提问作者agelter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:49:36