Python“来自”用法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24752395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 05:07:53  来源:igfitidea点击:

Python "raise from" usage

pythonpython-3.xsyntaxexception-handling

提问by darkfeline

What's the difference between raiseand raise fromin Python?

Python 中的raise和 有什么区别raise from

try:
    raise ValueError
except Exception as e:
    raise IndexError

which yields

这产生

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError
IndexError

and

try:
    raise ValueError
except Exception as e:
    raise IndexError from e

which yields

这产生

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError from e
IndexError

采纳答案by Martijn Pieters

The difference is that when you use from, the __cause__attributeis set and the message states that the exception was directly caused by. If you omit the fromthen no __cause__is set, but the __context__attributemay be set as well, and the traceback then shows the context as during handling something else happened.

不同之处在于,当您使用 时from,会设置该__cause__属性,并且消息指出异常是由 直接引起的。如果省略from则 no__cause__被设置,但__context__属性也可能被设置,然后回溯会显示上下文,就像在处理其他发生的事情时一样

Setting the __context__happens if you used raisein an exception handler; if you used raiseanywhere else no __context__is set either.

__context__如果您raise在异常处理程序中使用,则设置发生;如果您raise在其他任何地方使用,也没有__context__设置。

If a __cause__is set, a __suppress_context__ = Trueflag is also set on the exception; when __suppress_context__is set to True, the __context__is ignored when printing a traceback.

如果__cause__设置了 a __suppress_context__ = True,则异常也会设置一个标志;当__suppress_context__被设定为True,在__context__打印时,回溯忽略。

When raising from a exception handler where you don'twant to show the context (don't want a during handling another exception happenedmessage), then use raise ... from Noneto set __suppress_context__to True.

从异常处理程序,你养的时候希望显示上下文(不想处理另一个异常发生时,然后用消息)raise ... from None来设置__suppress_context__True

In other words, Python sets a contexton exceptions so you can introspect where an exception was raised, letting you see if another exception was replaced by it. You can also add a causeto an exception, making the traceback explicit about the other exception (use different wording), and the context is ignored (but can still be introspected when debugging). Using raise ... from Nonelets you suppress the context being printed.

换句话说,Python 为异常设置了一个上下文,以便您可以自省引发异常的位置,让您查看是否有另一个异常被它替换。您还可以为异常添加原因,使回溯明确关于另一个异常(使用不同的措辞),并且上下文被忽略(但在调试时仍然可以自省)。使用raise ... from None可让您抑制正在打印的上下文。

See the raisestatement documenation:

请参阅raise声明文档

The fromclause is used for exception chaining: if given, the second expressionmust be another exception class or instance, which will then be attached to the raised exception as the __cause__attribute (which is writable). If the raised exception is not handled, both exceptions will be printed:

>>> try:
...     print(1 / 0)
... except Exception as exc:
...     raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

A similar mechanism works implicitly if an exception is raised inside an exception handler or a finallyclause: the previous exception is then attached as the new exception's __context__attribute:

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

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

>>> try:
...     print(1 / 0)
... except Exception as exc:
...     raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

如果在异常处理程序或finally子句中引发异常,则类似的机制会隐式工作:然后将先前的异常附加为新异常的__context__属性:

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

Also see the Built-in Exceptions documentationfor details on the context and cause information attached to exceptions.

另请参阅内置异常文档以获取有关上下文和附加到异常的原因信息的详细信息。