1. ホーム
  2. パイソン

[解決済み】Pythonの "raise from "の使い方

2022-03-29 05:09:17

質問

とはどう違うのですか? raiseraise from をPythonで使うのですか?

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

解決方法は?

この違いは from は、その __cause__ 属性 が設定され、メッセージには、例外が 直接の原因は . を省略した場合は from を使用すると __cause__ が設定されますが __context__ 属性 が設定されている場合もあり、その場合、トレースバックではコンテキストが 処理中に別のことが起こった .

を設定する。 __context__ を使用した場合に発生します。 raise を例外ハンドラで使用した場合。 raise それ以外の場所では __context__ も設定されています。

もし __cause__ が設定されている場合は __suppress_context__ = True フラグも例外に設定されます。 __suppress_context__ に設定されます。 True を使用する場合、その __context__ はトレースバックを表示する際に無視されます。

例外ハンドラから発生させる場合 しない コンテキストを表示したい(たとえば 処理中に別の例外が発生した メッセージ)を使用する場合は raise ... from None を設定します。 __suppress_context__ から True .

つまり、Pythonは コンテキスト これにより、ある例外が発生した場所をイントロスペクトすることができ、別の例外がその例外に置き換わったかどうかを確認することができます。また 原因 を例外に追加すると、トレースバックに他の例外が明示されます (別の表現を使用します)。また、コンテキストは無視されます (ただし、デバッグ時にイントロスペクトすることは可能です)。使用方法 raise ... from None を使用すると、コンテキストが表示されないようにすることができます。

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

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

もご覧ください。 組み込みの例外に関する文書 は、例外に付随するコンテキストや原因情報の詳細について説明します。