Python:即使在try/except子句中捕获,异常仍然会被引发

5

在我的代码中,当出现异常时,我想捕获异常并将一些关于异常的信息打印到屏幕上,然后在完成操作后结束脚本。我尝试使用类似以下代码的内容,但我不明白为什么我会得到跟踪错误。

执行以下代码时:

try:
    1 / 0
except ZeroDivisionError:
    print("Exception: ZeroDivisionError")
    raise Exception

控制台输出:

Exception: ZeroDivisionError
Traceback (most recent call last):
  File "<pyshell#19>", line 2, in <module>
    1 / 0
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#19>", line 5, in <module>
    raise Exception
Exception

我原以为如果捕获了ZeroDivisionError,它就不会再被触发,只有我在结尾处写的raise Exception才会显示,但是两者都在控制台中显示。

为什么两者都显示,如何修改代码使只有第二个显示,或者有更好的方法实现我的目标?

1个回答

6

这里的控制台显示了上下文信息。当在异常处理程序中抛出异常时,Python会将当前异常附加到__context__属性中,如果新的异常没有被处理,Python稍后会显示该上下文信息。如果您不想显示上下文信息,则需要提供一个原因;您可以使用raise ... from None提供一个空原因:

try:
    1 / 0
except ZeroDivisionError:
    print("Exception: ZeroDivisionError")
    raise Exception from None

引用自 raise 语句文档

from 子句用于异常链接: 如果给定,第二个表达式必须是另一个异常类或实例,然后将其作为 __cause__ 属性(可写)附加到已引发的异常上。如果未处理该异常,则两个异常都将被打印[...]

如果在异常处理程序中引发异常,则会隐式地启用类似的机制:先前的异常随后作为新异常的 __context__ 属性附加[...]

而从 异常文档 中得知:

When raising (or re-raising) an exception in an except clause __context__ is automatically set to the last exception caught; if the new exception is not handled the traceback that is eventually displayed will include the originating exception(s) and the final exception.

When raising a new exception (rather than using a bare raise to re-raise the exception currently being handled), the implicit exception context can be supplemented with an explicit cause by using from with raise:

raise new_exc from original_exc

The expression following from must be an exception or None. It will be set as __cause__ on the raised exception. Setting __cause__ also implicitly sets the __suppress_context__ attribute to True, so that using raise new_exc from None effectively replaces the old exception with the new one for display purposes (e.g. converting KeyError to AttributeError), while leaving the old exception available in __context__ for introspection when debugging.

The default traceback display code shows these chained exceptions in addition to the traceback for the exception itself. An explicitly chained exception in __cause__ is always shown when present. An implicitly chained exception in __context__ is shown only if __cause__ is None and __suppress_context__ is false.


在Python shell中,raise Exception from None会导致SyntaxError。这是自然行为吗? - Sencer H.
1
@SencerH:这仅适用于Python 3。如果您看到语法错误,则正在使用Python 2。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接