場当たり的な例外処理
定期的に動かすので、ある程度きちんとプログラムを書かないといけないけど、そんなに丁寧に例外処理を書いている余裕はないぞというケースがある。
そういう時、実行スクリプトでは、このように雑に例外処理を行うことが多い。 こうしておけば、とりあえずどんな例外もログに吐き出すことができ、未知の例外に遭遇した時はエラーメッセージを見ながら、適宜コードを修正することができる。
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()
Read other posts