python - 使用“raise from”语法时链式异常的完整回溯
问题描述
给定文件errors.py
:
from traceback import format_tb, extract_tb
class MyError(Exception):
def __init__(self, message):
self.message = message
class MySecondError(Exception):
def __init__(self, message):
self.message = message
try:
try:
raise MyError("Something specific has happened")
except Exception as error:
raise MySecondError("Something general has happened") from error
except Exception as error:
print("".join(format_tb(error.__traceback__)))
运行python errors.py
时输出为:
File "errors.py", line 15, in <module>
raise MySecondError("Something general has happened") from error
这样做的主要问题是只有“链”中“最高”错误的回溯(MySecondError
),并且没有关于包装错误的信息(MyError
)
如果我删除最终try/except
包装器以便不捕获链接错误,我会得到更好的输出:
Traceback (most recent call last):
File "exceptions.py", line 14, in <module>
raise MyError("Something specific has happened")
__main__.MyError: Something specific has happened
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "exceptions.py", line 16, in <module>
raise MySecondError("Something general has happened") from error
__main__.MySecondError: Something general has happened
它具有完整错误链的回溯以及每个错误的连接行 ( Traceback (most recent call last):
, The above exception was the direct cause of the following exception:
)和字符串表示
理想情况下,我想捕获这些输出行以将它们引导到其他地方(例如记录器)
我的一种解决方案是迭代error.__context__
并手动添加连接短语:
except Exception as error:
inner_error = error
while inner_error:
if inner_error is not error:
print("\nThe above exception was the direct cause of the following exception:\n")
print("Traceback (most recent call last):")
print("".join(format_tb(inner_error.__traceback__) + [ str(error) ]))
inner_error = inner_error.__context__
哪个有效,但它很hacky,我更愿意使用一些已经处理这个的标准库模块。
解决方案
您想使用以下format_exception
功能:
from traceback import format_tb, format_exception
class MyError(Exception):
def __init__(self, message):
self.message = message
class MySecondError(Exception):
def __init__(self, message):
self.message = message
try:
try:
raise MyError("Something specific has happened")
except Exception as error:
raise MySecondError("Something general has happened") from error
except Exception as error:
print("".join(format_exception(error.__class__, error, error.__traceback__)))
给出:
$ python3 /tmp/a.py
Traceback (most recent call last):
File "/tmp/a.py", line 13, in <module>
raise MyError("Something specific has happened")
MyError: Something specific has happened
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/tmp/a.py", line 15, in <module>
raise MySecondError("Something general has happened") from error
MySecondError: Something general has happened
如果您指定chain=False
此函数将不会打印联合异常,而只会打印最后一个异常。
推荐阅读
- node.js - 为什么在每次查询后连接并关闭 mongodb 客户端?
- math - OpenSCAD:如何从向量到向量绘制圆柱体?
- angular - 从 HTML/Angular 应用程序访问移动相机
- sql-server - 无法检索所有启用的更改跟踪数据库
- python - 找不到模块“Firebase”错误
- django - Django中不允许的方法(405 POST)
- ios - 无法识别的选择器发送到实例 - 如何修复:从相册加载图片时出错
- python - Python init 没有看到类变量
- android - 适用于 Android 的 Google Drive API 上传文件但无法同步到远程
- python - 如何防止输入在python 3中开始新行