Python Click如何在解析选项前检查子命令前置执行条件?
Click子命令前置校验实现方案
你需要的在选项解析前执行前置校验的需求可以通过以下两种方案实现:
方案1:自定义命令类重写parse_args方法(最稳妥,100%在参数解析前执行)
Click的命令执行流程中,parse_args方法是解析所有选项、触发prompt回调的前置步骤,我们只要重写该方法,在调用父类解析逻辑前先执行校验即可:
import click # 自定义支持前置校验的命令类 class PreCheckCommand(click.Command): def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: # 先执行绑定的前置校验函数 if hasattr(self, "pre_check"): self.pre_check() # 校验通过后再解析参数 return super().parse_args(ctx, args) # 你的校验函数示例 def check_2(): # 这里写读取git状态判断sub1是否执行的逻辑 sub1_executed = False # 替换为实际校验逻辑 if not sub1_executed: raise click.ClickException("错误:请先执行 sub1 命令后再操作") def check_3(): # 这里写判断sub2是否执行的逻辑 sub2_executed = False # 替换为实际校验逻辑 if not sub2_executed: raise click.ClickException("错误:请先执行 sub2 命令后再操作") @click.group() def cli(): pass # 修正你原代码中@cli.command(debug)的错误写法 @cli.command() @click.option('--debug/--no-debug', default=False) def sub1(debug): # 操作git仓库的代码 pass # sub2指定使用自定义命令类,绑定校验函数 @cli.command(cls=PreCheckCommand) @click.option('--yes', type=bool, default=False, prompt="是否确认执行") def sub2(yes): # 对git仓库执行其他操作的代码 pass sub2.pre_check = check_2 # sub3同理绑定对应校验 @cli.command(cls=PreCheckCommand) @click.option('--yes', type=bool, default=False, prompt="是否确认执行") def sub3(yes): # 对git仓库执行最后操作的代码 pass sub3.pre_check = check_3 if __name__ == "__main__": cli()
该方案会在用户输入cli sub2后第一时间执行校验,校验不通过直接抛出错误,完全不会触发--yes选项的prompt回调,符合你的需求。
方案2:使用上下文before_invoke钩子(更简洁)
如果不想自定义类,也可以在组命令的回调中注册前置钩子,该钩子会在子命令参数解析前执行:
@click.group() @click.pass_context def cli(ctx): def pre_check_hook(ctx): if ctx.invoked_subcommand == "sub2": check_2() elif ctx.invoked_subcommand == "sub3": check_3() ctx.before_invoke(pre_check_hook)
该写法无需修改子命令的定义,适合子命令数量不多的场景。
内容的提问来源于stack exchange,提问作者emonier
相关产品推荐
相关产品推荐

