函数包装时 Python 异常堆栈跟踪不完整

问题描述 投票:0回答:1

我有两个文件

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

如何在没有包装器的情况下获得包装函数中的完整堆栈跟踪?谢谢!

python exception wrapper python-decorators
1个回答
0
投票

由于您抓取堆栈跟踪并在执行气泡返回到在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
    
© www.soinside.com 2019 - 2024. All rights reserved.