Pythonでプログラムを書いていて、「エラーが起きても起きなくても、必ずこの処理だけは通したい」という場面はありませんか?
例えば、ファイルのクローズやネットワーク接続の切断、DBのセッション終了など、いわゆる「後片付け(リソース解放)」です。これを確実に行うのがtry...finallyブロックです。
さらに、ループ処理の中でcontinueを使った場合にfinallyがどう動くのかを知っておくと、バグの少ない堅牢なコードが書けるようになります。
1. try-finallyの基本構造
まずは基本のおさらいです。finally節に書かれたコードは、tryブロック内で例外が発生したかどうかに関わらず、必ず最後に実行されます。
try:
print("処理を開始します")
# ここで何らかの処理
except Exception as e:
print(f"エラー発生: {e}")
finally:
print("必ず実行される後片付け処理です")2. ループ内での「continue」との組み合わせ
ここが本題です。for文やwhile文の中でtry...finallyを使い、さらにcontinueで処理をスキップしようとした場合、finallyはどうなるでしょうか?
結論から言うと、continueで次のループに飛ぶ直前に、必ずfinallyが実行されます。
サンプルコード
items = [1, 2, 0, 4]
for i in items:
print(f"--- ターゲット: {i} ---")
try:
if i == 0:
print("0なのでスキップします(continue)")
continue
result = 10 / i
print(f"計算結果: {result}")
finally:
print("この数値の処理を終了します(finally)")実行結果
--- ターゲット: 1 ---
計算結果: 10.0
この数値の処理を終了します(finally)
--- ターゲット: 2 ---
計算結果: 5.0
この数値の処理を終了します(finally)
--- ターゲット: 0 ---
0なのでスキップします(continue)
この数値の処理を終了します(finally) <-- ここに注目!
--- ターゲット: 4 ---
計算結果: 2.5
この数値の処理を終了します(finally)i == 0 の時、continueが呼ばれても、しっかりとfinallyの中身が実行されてから次のループ(i == 4)へ移っているのがわかります。
3. どんな場面で使えるのか?(実戦向けユースケース)
「continueしてもfinallyが動く」という特性は、以下のようなケースで非常に強力です。
① 大量ファイルのバッチ処理
複数のログファイルを読み込んで解析する際、1つのファイルが壊れていても処理を中断させたくない(continueしたい)、でも開いたファイルは確実に閉じたい場合です。
file_list = ["data1.txt", "corrupt.txt", "data2.txt"]
for filename in file_list:
f = open(filename, "r")
try:
content = f.read()
if "ERROR" in content:
continue # エラーがあれば次のファイルへ
process(content)
finally:
f.close() # continueしても、正常終了しても必ず閉じられる
print(f"{filename} をクローズしました")② 通信リトライ処理
APIへのリクエストなどで、特定のレスポンスコードが返ってきた際に「今回の処理はスキップしてリトライ」する場合でも、一時的なバッファのクリアやログ出力をfinallyで行うことができます。
4. 注意点:returnとの関係
finallyは最強です。関数内でtryブロックの中にreturnを書いても、finallyが実行されてから値が返ります。 (※finally内でreturnを書くと、try側の戻り値が上書きされてしまうため注意が必要です!)
まとめ:堅牢なコードにはfinallyが不可欠
Pythonのtry...finallyは、continueやbreak、さらにはreturnにさえ割り込んで実行される非常に義理堅いブロックです。
- リソースの解放漏れを防ぐ
- ループ処理の進捗を確実に記録する
これらを意識して、現場で使えるプロのPythonコードを目指しましょう。


コメント