在Python(3.10)中,一个异常在try中引发,包含一个不会扩展到try的调用位置的回溯. 这对我来说有点令人惊讶,更重要的是,这不是我想要的.

这里有一个简短的程序来说明这个问题:

# short_tb.py
import traceback


def caller():
    somefunction()


def somefunction():
    try:
        raise ValueError("This is a value error")
    except ValueError as e:
        # in my actual code, e is passed to a function, and __traceback__ is pulled from it for logging at this other
        # location; the code below simply demonstrates the lack of frames in the traceback object
        print("".join(traceback.format_tb(e.__traceback__)))


print("This will produce a traceback with only one frame, the one in somefunction()")
caller()


def caller2():
    somefunction2()


def somefunction2():
    raise ValueError("This is a value error")


print("This will produce a traceback with all relevant frames (the default behavior of the python interpreter)")
caller2()

输出:

This will produce a traceback with only one frame, the one in somefunction()
  File ".../short_tb.py", line 10, in somefunction
    raise ValueError("This is a value error")

This will produce a traceback with all relevant frames (the default behavior of the python interpreter)
Traceback (most recent call last):
  File ".../short_tb.py", line 30, in <module>
    caller2()
  File ".../short_tb.py", line 22, in caller2
    somefunction2()
  File ".../short_tb.py", line 26, in somefunction2
    raise ValueError("This is a value error")
ValueError: This is a value error

我希望__traceback__包含第二个例子中的所有信息.我很高兴覆盖变量,我可以在异常处理位置这样做.但是我如何才能得到一个对象来实现这个目的呢?

在这个问题中,有很多关于追溯的答案,但似乎没有一个是关于traceback objects的: Catch and print full Python exception traceback without halting/exiting the program

推荐答案

@ Mark Tolonen已经提出了更正确的处理方法,但是如果真的需要__traceback__来包含一个完整的堆栈:

  • 使用tb_frame.f_back访问前一帧.
  • 使用types.TracebackType重建追溯对象.
  • tb_next个构造函数参数将它们联系起来.
import traceback
import types


def caller(full = False):
    somefunction(full)

def somefunction(full):
    try:
        raise ValueError("This is a value error")
    except ValueError as e:
        if full:
            complete_traceback(e)
        print("".join(traceback.format_tb(e.__traceback__)))

def complete_traceback(exception):
    t = exception.__traceback__
    fb = t.tb_frame.f_back
    while fb:
        t = types.TracebackType(tb_next=t,
                                tb_frame=fb,
                                tb_lasti=fb.f_lasti,
                                tb_lineno=fb.f_lineno)
        fb = t.tb_frame.f_back
    exception.__traceback__ = t


print("This will produce a traceback with only one frame, the one in somefunction()")
caller()

print("This will produce a traceback with all relevant frames")
caller(True)

输出:

This will produce a traceback with only one frame, the one in somefunction()
  File ".../short_tb.py", line 10, in somefunction
    raise ValueError("This is a value error")

This will produce a traceback with all relevant frames
  File ".../short_tb.py", line 32, in <module>
    caller(True)
  File ".../short_tb.py", line 6, in caller
    somefunction(full)
  File ".../short_tb.py", line 10, in somefunction
    raise ValueError("This is a value error")

Python相关问答推荐

将特定列信息移动到当前行下的新行

非常奇怪:tzLocal.get_Localzone()基于python3别名的不同输出?

log 1 p numpy的意外行为

梯度下降:简化要素集的运行时间比原始要素集长

优化器的运行顺序影响PyTorch中的预测

在Django admin中自动完成相关字段筛选

Pandas Loc Select 到NaN和值列表

如何在图中标记平均点?

字符串合并语法在哪里记录

AES—256—CBC加密在Python和PHP中返回不同的结果,HELPPP

未调用自定义JSON编码器

ConversationalRetrivalChain引发键错误

如何创建引用列表并分配值的Systemrame列

如何在一组行中找到循环?

如何使用Azure Function将xlsb转换为xlsx?

ModuleNotFoundError:Python中没有名为google的模块''

PySpark:如何最有效地读取不同列位置的多个CSV文件

随机森林n_估计器的计算

正则表达式反向查找

Django REST框架+Django Channel->;[Errno 111]连接调用失败(';127.0.0.1';,6379)