見出し画像

【Python3】例外発生時、Exceptionにファイル名と行数を追加してエラーメッセージをわかりやすくする

「float divition by zero」と一言だけ言われても困るんですよ。

結論

sys.exc_info()で取れる

# 例外を一旦受け取って再送しているファイルを想定
import sys

try:
    result = 1 / 0  # ZeroDivisionErrorが起きる
except Exception as e:
    exception_type, exception_object, exception_traceback = sys.exc_info()
    filename = exception_traceback.tb_frame.f_code.co_filename
    line_no = exception_traceback.tb_lineno
    raise Exception(f"{filname}{line_no}行目でエラーが発生しました。詳細:{e}")

自作例外クラス作ってもうちょっと扱いやすくしても良いかも知れないですが、とりあえず。

何がしたいか

既に丁寧な例外処理が仕込まれているプロジェクトにちょいと手を入れたら突然「float divition by zero」というエラーが出るようになってしまいまして、しかもflaskアプリで、統合テストでしか出てこない、ついでに自分で作ったやつじゃない、というね、なんとも検証しづらいやつ。
丁寧な例外処理が仕込まれているが為に、表示されるエラーが「float divition by zero」一言で、どのファイルの何行目で起きているのかもわかりません。困った。

え?Logger使え?まあ、それはそう。(それはそう)
今から入れるのちょっと大変だから……

あと、ずっと不便だなぁと思いながらもほったらかしてたんですけど、メール等でエラー通知をするときに、

except Exception as e:
    message = str(e)
    my_send_error_mail(e)

とかでね、雑にエラー発生通知投げてると、これも「float divition by zero」ひとことだけメールされてきて、エラーが起きたことは分かるけど具体的にどこで何が起きたのかさっぱり、っていうこともよくありますね。

たいていは、

except Exception as e:
    raise MyException(f"〇〇の処理中に▼▼なエラーが発生しました。詳細:{e}")

こんな風にしてね、エラーメッセージだけ転送すれば十分なメッセージが届くように作ってあるつもりで、予期せぬエラーが突然起きたときに、急に謎の英文が一文だけ届いて呆然とするんだ。

ということで、表示されるエラーメッセージ内に、Exeptionオブジェクトが持っているはずのもっと詳しい情報を加えてあげたいと思います。

……Loggerのメール送信機能使った方が早い?
それはそう。(それはそう)
でもまあ、諸般の事情でね。使えない場合もあるのでね。はい。

エラー詳細の取り出し方

Exceptionオブジェクトが色々持っていそうな気がしましたが、公式ドキュメントを見ると全然何も保持していないことがわかります。メッセージしか持ってないじゃないですか~~

じゃあStack traceとかで表示される詳細情報はどこに入ってるのか、というとsysが持ってます。

import sys
exception_type, exception_object, exception_traceback = sys.exc_info()

で、例外の型・Exeptionオブジェクトそもの・TraceBackに表示されるいろいろ、を取得することができます。

主に必要なものはexception_tracebackとして入ってきます。
とりあえず今欲しいのは、例外が発生したファイル名と行番号なので、以下のように取得することができました。ありがとうVScodeのオブジェクトツリー表示機能とGitHub Copilot。

print(f"エラーが起きたファイル名:{exception_traceback.tb_frame.f_code.co_filename}")
print(f"行番号:{exception_traceback.tb_lineno}")

というわけで、この情報を例外発生時のメッセージに仕込んでやれば、最終的な出力にもファイル名と行番号を入れ込むことが出来ました。やったね。

この記事が気に入ったらサポートをしてみませんか?