Python装饰器错误处理:如何让循环执行完毕而非提前终止函数?
问题:错误处理后循环中途终止,如何让循环继续执行?
我希望在处理每个错误(数字6到9触发的错误)后,循环能继续执行至结束。但目前程序在i==6时就中途终止了。我使用装饰器进行错误处理,请问哪里出错了?
class SomeError(Exception): pass def do_something_helper(number: int) -> bool: if number > 5 and number < 10: raise SomeError(f"Some kind of error") else: return True def do_nothing(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except SomeError as e: print("Handle the error") return wrapper @do_nothing def do_something_main(number: int): for i in range(0, number): print(i) if do_something_helper(i): print("Next") else: print("Something's wrong") do_something_main(20)
程序运行输出:
0 Next 1 Next 2 Next 3 Next 4 Next 5 Next 6 Handle the error
原因分析
你现在的装饰器是加在整个do_something_main函数上的,这意味着整个主函数的执行都被包裹在装饰器的try-except块里。当循环执行到i=6时,do_something_helper抛出SomeError,这个异常会被装饰器的except捕获,处理完错误后,装饰器的wrapper函数就直接返回了,导致整个do_something_main函数终止,循环自然就停了。
简单说:你的错误处理范围太大,一次出错就直接结束了整个主函数,而不是只处理当前循环的错误并继续下一次循环。
解决方法
有两种常见的修正方式,选哪种看你的需求:
方式一:给do_something_helper加装饰器(推荐)
把装饰器应用到抛出异常的辅助函数上,这样每次调用helper出错时,装饰器处理完异常后会返回一个值,让主函数的循环能继续执行:
class SomeError(Exception): pass def do_nothing(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except SomeError as e: print("Handle the error") # 原函数返回bool,这里返回False让主函数的if判断能继续 return False return wrapper # 把装饰器移到helper函数上 @do_nothing def do_something_helper(number: int) -> bool: if number > 5 and number < 10: raise SomeError(f"Some kind of error") else: return True def do_something_main(number: int): for i in range(0, number): print(i) if do_something_helper(i): print("Next") else: print("Something's wrong") do_something_main(20)
方式二:在循环内部直接捕获异常
如果不需要用装饰器,也可以直接在循环里调用helper的地方加try-except,精准处理单次循环的错误:
class SomeError(Exception): pass def do_something_helper(number: int) -> bool: if number > 5 and number < 10: raise SomeError(f"Some kind of error") else: return True def do_something_main(number: int): for i in range(0, number): print(i) try: if do_something_helper(i): print("Next") else: print("Something's wrong") except SomeError as e: print("Handle the error") print("Something's wrong") do_something_main(20)
这两种方式都能让循环在处理完6-9的错误后,继续执行到i=19。
内容的提问来源于stack exchange,提问作者gobigorgobald
相关产品推荐
相关产品推荐

