Python の「raise from」の使い方 質問する

Python の「raise from」の使い方 質問する

Python のraiseとの違いは何ですか?raise 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

ベストアンサー1

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

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

が設定されている場合__cause____suppress_context__ = True例外にフラグも設定されます。 が__suppress_context__に設定されている場合True__context__トレースバックを出力するときに は無視されます。

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

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

を参照してくださいraise声明文書:

このfrom句は例外の連鎖に使用されます。指定されている場合、2 番目の式は別の例外クラスまたはインスタンスである必要があり、発生した例外に属性 (書き込み可能) として添付されます__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

以下も参照組み込み例外ドキュメント例外に付随するコンテキストと原因情報の詳細。

おすすめ記事