Python装饰器包装函数时栈追踪信息不完整的解决咨询
问题:保留装饰器时获取完整栈追踪
场景复现
现有两个文件t.py和t2.py:
t.py代码
import functools import traceback def wrapper(func): @functools.wraps(func) def wrapped(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: traceback.print_exception(e) return wrapped @wrapper def problematic_function(): raise ValueError("Something went wrong")
t2.py代码
from t import problematic_function problematic_function()
执行命令python t2.py时,当前装饰器中用traceback.print_exception(e)打印的栈追踪丢失了t2.py的调用信息:
Traceback (most recent call last): File "/home/c/t.py", line 9, in wrapped return func(*args, **kwargs) File "/home/c/t.py", line 18, in problematic_function raise ValueError("Something went wrong") ValueError: Something went wrong
而移除装饰器后,能得到包含t2.py调用信息的完整栈追踪:
Traceback (most recent call last): File "/home/c/t2.py", line 3, in <module> problematic_function() File "/home/cu/t.py", line 17, in problematic_function raise ValueError("Something went wrong") ValueError: Something went wrong
如何在保留装饰器的情况下获取与无装饰器时一致的完整栈追踪?
解决方案
修改t.py中的异常处理逻辑,替换traceback.print_exception(e)为traceback.print_exc()即可。
修改后的t.py代码
import functools import traceback def wrapper(func): @functools.wraps(func) def wrapped(*args, **kwargs): try: return func(*args, **kwargs) except Exception: # 使用print_exc自动捕获完整调用链 traceback.print_exc() return wrapped @wrapper def problematic_function(): raise ValueError("Something went wrong")
原理说明
traceback.print_exception(e)仅传入异常实例,它会从异常的__traceback__属性提取栈信息,该属性仅记录从异常抛出点到当前except块的栈帧,因此截断了t2.py的调用链。而traceback.print_exc()会自动捕获当前异常的完整上下文(包括整个调用链的所有栈帧),从而能显示t2.py中的调用记录。
内容的提问来源于stack exchange,提问作者hovnatan
相关产品推荐
相关产品推荐

