如何让Python Click框架在出错时仍执行回调函数?
解决Click命令执行后始终运行代码的问题
你遇到的核心问题是:@cli.result_callback()仅在命令成功完成且未抛出异常时才会触发,异常场景下不会执行回调逻辑。要实现无论命令成功或失败都执行收尾代码,可采用以下几种方案:
方法一:使用context.call_on_close()(推荐)
这是Click官方支持的方式,通过上下文注册关闭回调,无论命令执行成功、抛出异常还是被中断,注册的函数都会被调用。
修改后的代码如下:
import click @click.group() @click.pass_context def cli(ctx) -> None: """lorem ipsum""" print("whatever") # 注册全局收尾函数 ctx.call_on_close(cleanup) def cleanup(): print("this should always appear") @click.command() def command1() -> None: raise Exception("blah") # 修正原代码的语法错误 @click.command() def command2() -> None: print("hi") cli.add_command(command1) cli.add_command(command2) if __name__ == "__main__": cli()
方法二:自定义Group类包裹执行逻辑
通过重写Group的invoke方法,用try/finally强制保证收尾代码执行:
import click from click.core import Group class CleanupGroup(Group): def invoke(self, ctx): try: return super().invoke(ctx) finally: print("this should always appear") @click.group(cls=CleanupGroup) def cli() -> None: """lorem ipsum""" print("whatever") @click.command() def command1() -> None: raise Exception("blah") @click.command() def command2() -> None: print("hi") cli.add_command(command1) cli.add_command(command2) if __name__ == "__main__": cli()
方法三:给单个命令添加局部异常处理(不推荐)
如果命令数量极少,也可以给每个命令单独加try/finally,但这种方式会产生冗余代码:
import click @click.group() def cli() -> None: """lorem ipsum""" print("whatever") def cleanup(): print("this should always appear") @click.command() def command1() -> None: try: raise Exception("blah") finally: cleanup() @click.command() def command2() -> None: try: print("hi") finally: cleanup() cli.add_command(command1) cli.add_command(command2) if __name__ == "__main__": cli()
额外说明
- 已修正原代码中
raise Exception"blah")的语法错误,正确写法为raise Exception("blah") - 方法一的
call_on_close是最简洁且符合Click设计理念的方案,优先推荐使用
内容的提问来源于stack exchange,提问作者J.D. Palomino
相关产品推荐
相关产品推荐

