[英]What is the reason to use exception chaining
最近我在阅读有关异常链接的内容,我不确定何时应该使用这种语法,以及出于什么原因。
我习惯了这样的模式:
try:
my_function()
exception MyError:
my_logger.exception("Error occured")
raise MyProcessError("Process failed")
我注意到,如果我在这里使用异常链接,回溯中的一个文本将被更改,并且 MyProcessError 将具有来自 MyError 的消息的新属性。
try:
my_function()
exception MyError as err:
my_logger.exception("Error occured")
raise MyProcessError("Process failed") from err
跟踪日志中提到的更改是将“在处理上述异常期间,发生另一个异常”替换为“上述异常是以下异常的直接原因”。
那么使用这种语法的原因是什么? 我什么时候应该将它包含到我的代码中? 欢迎提供示例:-)
在异常处理程序中,如果您显式引发异常,您将希望使用from err
或from None
(取决于抑制原始回溯是否更有意义)。
如果没有from
,您会收到消息:“在处理上述异常期间,发生了另一个异常”,表明“出了点问题,然后,在尝试从中恢复时,其他事情(可能不相关)出了问题。就是这种情况例如,当您打错字( my_logger.expeption("Error occurred")
)或尝试将某些内容保存到无法打开的文件时。
与from
,它表明只有一件事情出错了,你没有处理自己,但你有一些对程序员或用户有用的信息。 例如,您可以捕获KeyError
并使用消息“试图编辑不存在的小部件”或其他任何内容引发不同的异常。
因此raise SomeException("some description") from err
是一种能够解释如果引发err
的代码无法做到这一点时出现错误的方法(因为它来自标准库,或者因为它缺乏必要的上下文它被称为),而没有让用户认为两个独立的事情相继出错。
语句raise EXCEPTION from CAUSE
等价于:
exc = EXCEPTION
exc.__cause__ = CAUSE
raise exc
此功能有时可用于存储有关异常链的信息,以便在最后一级处理、传输或记录。
例如,在创建自己的库时,我们使用基础 class 创建自己的异常层次结构,并且我们不想从函数中抛出第三个库的异常。 但同时,我们希望将有关原始异常的信息保存为详细信息。
class ThirdPartyLibException(Exception):
pass
def third_party_lib_foo():
...
raise ThirdPartyLibException('third party exception')
class MyLibException(Exception):
pass
def my_lib_foo():
try:
third_party_lib_foo()
except ThirdPartyLibException as e:
raise MyLibException() from e
try:
my_lib_foo()
except MyLibException as e:
print('True reason: ', str(e.__cause__))
# processing
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.