Python 3中如何抛出不含最后栈帧的异常并过滤回溯信息
Python3中移除装饰器栈帧的异常回溯处理方案
在Python3中,要实现和Python2一样的效果——让异常回溯不包含装饰器的栈帧,同时避免新增raise e.with_traceback(...)的记录,可以通过结合sys.exc_info()获取回溯信息并使用raise ... from None切断上下文来实现:
import sys import functools def exceptionCatcher(func): @functools.wraps(func) def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception: exc_type, exc_value, exc_tb = sys.exc_info() # 这里可以添加自定义日志逻辑 # 跳过装饰器wrapper的栈帧 trimmed_tb = exc_tb.tb_next # 重新抛出异常,from None避免添加当前raise语句的栈帧 raise exc_value.with_traceback(trimmed_tb) from None return wrapper def a(): raise Exception("My Exception") @exceptionCatcher def test(): a() # 测试调用 test()
原理说明:
sys.exc_info()获取当前异常的类型、实例和回溯对象,exc_tb.tb_next直接跳过了装饰器wrapper函数的栈帧,对应Python2中excInfo[2].tb_next的逻辑。raise ... from None是关键:默认情况下,Python3中重新抛出异常时会把当前raise语句所在的栈帧追加到回溯中,加上from None后会切断这个上下文关联,避免新增不必要的回溯记录。
这样处理后,异常的回溯信息就只会包含a()和test()的调用栈,完全排除了装饰器相关的栈帧和raise语句的记录,符合需求。
内容的提问来源于stack exchange,提问作者Jonas Sorgenfrei
相关产品推荐
相关产品推荐

