Pythonでフレームワークから発生した例外を元に、適切に自作した例外に変換する方法に複数あることを知ったので、それを素振りしました。
なお、結果だけ先にお伝えするとraise
するだけでも9割問題ありません。
環境
- Python
- 3.11.6
確認方法
Pythonでは単純にエラーをraise
するだけでなく、from e
とfrom None
という構文を付けてraise
することもできます。
try: try: 1 / 0 except ZeroDivisionError as e: raise ValueError("ERROR") # 1つ目 raise ValueError("ERROR") from e # 2つ目 raise ValueError("ERROR") from None # 3つ目 except Exception as e: print(traceback.format_exc())
具体的にtraceback.formt_exc()
で得られるstacktraceは次のとおりです。
# 1つ目のraise tests/unit/test_raise_error.py Traceback (most recent call last): File "/tests/unit/test_raise_error.py", line 9, in test_01 1 / 0 ~~^~~ ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/tests/unit/test_raise_error.py", line 11, in test_01 raise ValueError("ERROR") ValueError: ERROR
# 2つ目のraise Traceback (most recent call last): File "/tests/unit/test_raise_error.py", line 9, in test_01 1 / 0 ~~^~~ ZeroDivisionError: division by zero The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/tests/unit/test_raise_error.py", line 11, in test_01 raise ValueError("ERROR") from e ValueError: ERROR
# 3つ目のraise Traceback (most recent call last): File "/tests/unit/test_raise_error.py", line 11, in test_01 raise ValueError("ERROR") from None ValueError: ERROR
差分としては次のとおりです。
- 1つ目のやり方
- エラーメッセージに
During handling of the above exception, another exception occurr
が出力される- 例外処理中に例外が発生しました
- 2つ目のやり方
- エラーメッセージに
The above exception was the direct cause of the following exception
が出力される- 上記の例外が直接の原因で次の例外が発生しました
- 3つ目のやり方
- 元の例外を握りつぶす
結論
正確に例外を表現するならraise Error from e
を使用してください。
ライブラリやフレームワークを作成したり、テスト用の便利なモジュールを作っているときに、例外を伝播させたくないときにはraise Error from None
を使用してください。
Pythonとしては、例外は意図的に握りつぶさないので単純にraise
するだけでも9割のケースで問題ないでしょう。
ソースコード
終わりに
個人的に、raise from e
にはもう少し情報が増えることを期待していました。もちろん、正確に表現するならraise from e
があったほうが良いです。しかし、stacktraceを読もうとしているときは不具合の原因をいち早く確認したいので、まずは発生箇所を特定することを最優先してしまい、結果としてDuring handling of the above exception, another exception occurr
というメッセージは今まで目に入ってこなかったです。
まぁ、知識として知ったうえで単純にraise
することは今後無くなるでしょうが、かといって無理やり既存のコードにraise from e
を付与するほどではないので、結論としてはあまり気にしなくていいです。