如何在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中获取嵌套异常的堆栈跟踪?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Visual Studio 2017 中获取堆栈跟踪
获取 PL/SQL 中重新抛出异常的完整堆栈跟踪(从点异常开始)