Python の __exit__ で例外を処理する
__exit__() メソッドは、with ブロック内で発生した例外の情報を受け取ります。この情報を使って、例外を処理したり、ログを記録したり、例外を抑制したりできます。
exit の引数
__exit__() は3つの引数を受け取ります。
def __exit__(self, exc_type, exc_val, exc_tb):
passexc_type
例外のクラス(型)。例外がなければ None。
exc_val
例外のインスタンス(値)。例外がなければ None。
exc_tb
トレースバックオブジェクト。例外がなければ None。
例外情報の確認
例外が発生したかどうかは、exc_type が None かどうかで判断できます。
class ExceptionLogger:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None:
print("正常終了")
else:
print(f"例外発生: {exc_type.__name__}: {exc_val}")
return False
# 正常終了の場合
with ExceptionLogger():
print("処理中")
# 処理中
# 正常終了
# 例外発生の場合
with ExceptionLogger():
raise ValueError("エラーです")
# 例外発生: ValueError: エラーです
# (その後 ValueError が再送出される)例外の抑制
__exit__() が True を返すと、例外が抑制されて外部に伝播しません。
class SuppressError:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is ValueError:
print(f"ValueError を抑制: {exc_val}")
return True # 例外を抑制
return False # その他の例外は再送出
with SuppressError():
raise ValueError("無視される")
print("処理継続")
# ValueError を抑制: 無視される
# 処理継続return True
例外を抑制する。with ブロックの外には伝播しない。
return False(またはなし)
例外を再送出する。with ブロックの外に伝播する。
特定の例外のみ処理
例外の型をチェックして、特定の例外だけを処理することもできます。
class HandleFileError:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is FileNotFoundError:
print(f"ファイルが見つかりません: {exc_val}")
return True
elif exc_type is PermissionError:
print(f"権限がありません: {exc_val}")
return True
return False # その他の例外はそのまま
with HandleFileError():
open("存在しないファイル.txt")
print("処理継続")
# ファイルが見つかりません: [Errno 2] No such file or directory: '存在しないファイル.txt'
# 処理継続クリーンアップは必ず実行される
例外を抑制するかどうかに関わらず、__exit__() 自体は必ず呼び出されます。
class CleanupDemo:
def __enter__(self):
print("リソース確保")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("リソース解放") # 例外があっても実行される
return False
try:
with CleanupDemo():
raise RuntimeError("エラー")
except RuntimeError:
print("例外をキャッチ")
# リソース確保
# リソース解放
# 例外をキャッチ注意点
例外を抑制する場合は慎重に行いましょう。予期しない例外まで抑制してしまうと、バグの発見が困難になります。通常は特定の例外のみを抑制し、それ以外は再送出するのが安全です。











