使用异常链的原因是什么

问题描述 投票:0回答:2

最近我正在阅读有关异常链接的内容,我不确定何时应该使用此语法以及出于什么原因。

我已经习惯了这样的模式:

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

跟踪日志中提及的更改是将“在处理上述异常期间,发生了另一个异常”替换为“上述异常是以下异常的直接原因”。

那么使用这种语法的原因是什么?我什么时候应该将其包含到我的代码中? 欢迎举例 :-)

python python-3.x exception
2个回答
4
投票

在异常处理程序中,如果您显式引发异常,您将需要使用

from err
from None
(取决于抑制原始回溯是否更有意义)。

如果没有

from
,您收到的消息:“在处理上述异常期间,发生了另一个异常”,表明“出现了问题,然后,在尝试从中恢复时,出现了其他问题(可能不相关)。这例如,当您输入错误 (
my_logger.expeption("Error occurred")
) 或尝试将某些内容保存到无法打开的文件时,就会出现这种情况。

带有

from
,它表明只有一件事出了问题,即您没有处理自己,但您有一些对程序员或用户有用的更多信息。例如,您可以捕获
KeyError
并引发不同的异常,并显示消息“尝试编辑不存在的小部件”或其他内容。

因此,

raise SomeException("some description") from err
是一种能够解释如果引发
err
的代码无法做到这一点(因为它来自标准库,或者因为它缺乏必要的上下文)的方法。被调用),而不会让用户认为两个独立的事情接连发生了错误。


2
投票

声明

raise EXCEPTION from CAUSE
相当于:

exc = EXCEPTION
exc.__cause__ = CAUSE
raise exc

此功能有时对于存储有关异常链的信息以便在最后一级进行处理、传输或记录非常有用。

例如,在创建我们自己的库时,我们使用基类创建自己的异常层次结构,并且我们不想从我们的函数中抛出第三个库的异常。但同时,我们希望将原始异常的信息保存为详细信息。


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
© www.soinside.com 2019 - 2024. All rights reserved.