【Python】try-finallyの挙動を完全理解!ループ中のcontinueはどう動く?

この記事は約4分で読めます。

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は、continuebreak、さらにはreturnにさえ割り込んで実行される非常に義理堅いブロックです。

  • リソースの解放漏れを防ぐ
  • ループ処理の進捗を確実に記録する

これらを意識して、現場で使えるプロのPythonコードを目指しましょう。

コメント

タイトルとURLをコピーしました