如何在python中获取嵌套异常的堆栈跟踪?

Posted

技术标签:

【中文标题】如何在python中获取嵌套异常的堆栈跟踪?【英文标题】:How to get the stack trace of a nested exeption in python? 【发布时间】:2020-01-27 20:42:48 【问题描述】:

如果引发异常,我想分析 python 中的堆栈跟踪,以了解问题在源代码文件中的确切位置。

当然,为此目的,模块traceback 存在。这适用于常规异常。但是如果出现嵌套异常,该如何处理呢?

考虑这个例子:

def test():
    try:
        a = 0
        b = 5 / a
    except Exception as ee1:
        assert False

test()

这个例子打印了两个异常:

Traceback (most recent call last):
  File "./test4d.py", line 12, in test
    b = 5 / a
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./test4d.py", line 18, in <module>
    test()
  File "./test4d.py", line 14, in test
    assert False
AssertionError

因此,解释器知道有关这两种异常的信息。因此,我喜欢从 Python 中检索这两条信息:assert 语句的堆栈跟踪(此处用作示例以导致异常)和除以零异常的堆栈跟踪(此处用作示例以导致异常)例外)。 我该怎么做?

问题的第二部分:我怎样才能以结构化的方式做到这一点?模块traceback 可用于获取有关现有异常的更多信息。但我不想打印异常,我想存储它。因此,我想将堆栈跟踪作为某个类的实例的元组,其中每个实例代表每个堆栈帧中的数据。我该怎么做那个

【问题讨论】:

它没有回答您提出的问题,但raise...from 模式是导致嵌套异常的正确方法。 (在您的示例中,在我看来 ee1 应该在堆栈跟踪中,因为它被捕获了。) 非常感谢,Leporello。我对它进行了实验,但找不到解决方法。但是根据您的评论,我现在可以改写这个问题,所以现在更准确了。 (raise...from 的问题是:由于某种原因,我无法访问上一个堆栈跟踪。在重新引发异常时,旧堆栈跟踪似乎总是丢失。) 【参考方案1】:

有一个名为__context__ 的变量与异常相关联。此变量可用于访问嵌套异常。看这个例子:

import traceback

def test():
    try:
        a = 0
        b = 5 / a
    except Exception as ee1:
        assert False

try:
    test()
except Exception as ee:
    print(repr(ee))
    stackTraceList = traceback.extract_stack(ee.__traceback__.tb_frame)
    del stackTraceList[0]
    for frame in stackTraceList:
        print("\t", frame)

    if ee.__context__:
        print(repr(ee.__context__))
        stackTraceList = traceback.extract_stack(ee.__context__.__traceback__.tb_frame)
        del stackTraceList[0]
        for frame in stackTraceList:
            print("\t", frame)

这将输出以下文本:

AssertionError()
ZeroDivisionError('division by zero',)
     <FrameSummary file ./example.py, line 8 in test>

这表明两个异常都可以被识别,并且它们的堆栈跟踪可以被迭代。

为方便起见,我实现了一个简单的帮助模块来处理异常和堆栈跟踪,名为jk_exceptionhelper。您可以使用pip 安装此模块。有关详细信息,请查看 GIT 存储库:https://github.com/jkpubsrc/python-module-jk-exceptionhelper

【讨论】:

以上是关于如何在python中获取嵌套异常的堆栈跟踪?的主要内容,如果未能解决你的问题,请参考以下文章

Python:异常装饰器。如何保留堆栈跟踪

如何在 Visual Studio 2017 中获取堆栈跟踪

获取 PL/SQL 中重新抛出异常的完整堆栈跟踪(从点异常开始)

使用 sbt 和 testng 时,如何获取测试中抛出的异常的完整堆栈跟踪?

Javascript 异常堆栈跟踪

如何从像 Asp.Net 这样的堆栈跟踪中获取“源错误”?