web-dev-qa-db-ja.com

Python "raise from"の使用法

Pythonのraiseraise fromの違いは何ですか?

try:
    raise ValueError
except Exception as e:
    raise IndexError

をもたらす

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

そして

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

をもたらす

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
138
darkfeline

違いは、fromを使用すると、__cause__属性が設定され、メッセージには例外がによって直接引き起こされます。 fromを省略すると、__cause__は設定されませんが、__context__属性も設定できます、その後、トレースバックは、何かが起こったときの処理中にコンテキストをとして表示します

例外ハンドラーでraiseを使用した場合、__context__が設定されます。 raiseを他の場所で使用した場合、__context__も設定されません。

__cause__が設定されている場合、__suppress_context__ = Trueフラグも例外に設定されます。 __suppress_context__Trueに設定されている場合、トレースバックの印刷時に__context__は無視されます。

コンテキストを表示したくないしない例外ハンドラーから発生する場合(中に別の例外が発生したメッセージ)、raise ... from Noneを使用して__suppress_context__Trueに設定します。

言い換えると、Pythonは例外にcontextを設定するので、例外が発生した場所を内省して、別の例外を確認できます。それに置き換えられました。また、例外にcauseを追加して、他の例外について明示的にトレースバックを作成し(異なる表現を使用)、コンテキストを無視することもできます(ただし、デバッグ時にも内省されます)。 raise ... from Noneを使用すると、印刷されるコンテキストを抑制できます。

raiseステートメントのドキュメント を参照してください:

from句は、例外チェーンに使用されます。指定する場合、2番目のexpressionは別の例外クラスまたはインスタンスである必要があります。 __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

コンテキストの詳細と例外に付随する原因情報については、 組み込み例外ドキュメント も参照してください。

162
Martijn Pieters