我有两个文件
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
调用时,在 t2.py
中打印 traceback.print_exception(e)
时,包含来自 t.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
就像我删除装饰器一样,我得到:
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
如何在没有包装器的情况下获得包装函数中的完整堆栈跟踪?谢谢!
由于您抓取堆栈跟踪并在执行气泡返回到在t2.py
中运行的帧之前打印它,因此程序只是在完全执行您要求它执行的操作:这些帧不在堆栈跟踪中。 调用堆栈、为到达异常点而输入的帧保持分离 - 作为
Frame
对象中的链接链。该信息用于在异常未被捕获时将异常“冒泡”起来,但仅在到达每个外部级别时才将其添加到回溯中。既然你在
t
中捕获了异常,那就是你所拥有的。您必须“手动”内省框架才能获取任何调用者信息 - 您可以将框架作为回溯中的属性获取 - 或者,您可以只检查包装器本身内部的
sys._getframe()
调用,并跟踪外部通过遵循
.f_back
属性进行框架。当然,您想要收集的任何信息或在这些框架上打印的格式都在您自己的代码中。
def wrapper(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
# inner trace:
traceback.print_exception(e)
# outer trace:
f = sys._getframe()
while f:
print(f"{f.f_globals.get("__file__", <"unknown">} at line {f.f_lineno}")
f = f.f_back
# you could use `inspect.getsource` to print lines of code
return wrapped