我有两个文件 t.py:import functoolsimport traceback def wrapper(func): @functools.wraps(func) def wrapper(*args, **kwargs): try: return func(*args, **kwargs)
我有两个文件 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
在没有包装器的情况下,如何获取包装函数中的完整堆栈跟踪?谢谢!
您的代码会更改捕获(或未捕获)异常的位置,因此堆栈跟踪也会更改。异常的堆栈跟踪是从引发异常的位置到捕获异常的位置。这有点像 XY 问题。您想要实现什么目的?
执行回到正在运行的框架 之前 抓住堆栈跟踪并将其打印出来 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