Pythonでの雑でガバっとした例外処理
定期的に動かすので、ある程度きちんとプログラムを書かないといけないけど、そんなに丁寧に例外処理を書いている余裕はないぞというケースがある。
そういう時、実行スクリプトでは、このように雑に例外処理を行うことが多い。 こうしておけば、とりあえずどんな例外もログに吐き出すことができ、未知の例外に遭遇した時はエラーメッセージを見ながら、適宜コードを修正することができる。
import traceback try: a() b() c() d() e() except: msg = traceback.format_exc() mail_logger.error(msg)
ところでDB周りの業務をやっていると、SQLAlchemyを使って、下のようにsession_scope
関数を定義し、色んなところで使いまわす。
from contextlib import contextmanager @contextmanager def session_scope(): session = Session() try: yield session session.commit() except: session.rollback() finally: session.close() # session_scopeはこのように使う def insert(something): with session_scope() as session: session.add(something)
# メインの処理はこのような感じ try: something = Something() insert(something) except: msg = traceback.format_exc() mail_logger.error(msg)
しかし、このsession_scope
を上記のようなtry句内で使うと、DB操作で例外が発生した時に、session_scope
内のexcept
、finnaly
でプログラムが終了し、肝心の最上位のexcept
句に処理が到達しない。
こうなると、ログが吐き出されないので、困ったことになる。
こういうときは、session_scope
内のexcept
句の中で例外を再スローしてやるとよい。
そうすると、きちんと処理が最上位のexcept
にまで到達し、DB操作時に例外が発生した時の状況がログに書き込まれる。
from exceptions import DBHandleException @contextmanager def session_scope(): session = Session() try: yield session session.commit() except: session.rollback() # 例外を再スローする raise DBHandleException finally: session.close()