Pythonのfinallyによる例外処理後の必須実行処理と使い方をわかりやすく解説

スポンサーリンク
スポンサーリンク
amazon
スマイルSALE
--:--:--
ad. 価格範囲を指定して商品を探せます

finallyの概要

例外処理後の必須実行処理(後片付けの保証) Python予約語

finally

概要 finally(ファイナリー)は、try-except 構文の最末尾に結合し、内部でエラーが発生したかどうかに関わらず、最後に必ず100%実行されるブロックを定義するためのキーワードです。主に、開いたファイルを確実に閉じる、通信を切断するなど、プログラムの「後片付け(リソース解放)」を保証するために使用されます。

わかりやすく説明 finally は、プログラムにおける「絶対実行される現状復帰命令」です。たとえ途中の処理が大失敗してエラーに飛び火しても、逆にすべてが順調に終わって関数が途中で帰ろうとしても、Pythonは「それはそれとして、最後にこの片付けだけはやってから次に行きなさい!」と、finally の中身を必ず通過させます。

  • try ブロックが成功しても、except でエラーをキャッチしても、最終的に必ず実行されます。
  • 予期せぬエラーでシステムがクラッシュしかけた場合でも、データベース接続の切断などの重要な「鍵閉め作業」を安全に行えます。
  • except を省略し、tryfinally だけを組み合わせて「エラーは外に投げつつ、片付けだけは自分でする」という使い方も可能です。

finallyの考え方をイメージで理解

finallyの基本的な使い方(例外が起きない場合)

計算がエラーなくスムーズに進んだケースです。try の処理が終わった後、そのまま直通で finally が動きます。

# finally の基本(正常時)
try:
    print("【1】計算を開始します。")
    result = 10 / 2  # エラーは起きません
except ZeroDivisionError:
    print("【X】ゼロ除算エラーを検知しました。")
finally:
    print("【2】お片付け完了(必ず実行されます)。")
  • 画面には「【1】計算を開始します。」に続いて、except は無視され、最後に「【2】お片付け完了」が出力されます。

exceptと組み合わせたfinallyの使用(例外が起きた場合)

今度は try の中でエラーが発生したケースです。エラーを撃退したあとに、きっちり finally へ着地します。

# except と finally の組み合わせ(異常時)
try:
    print("【1】計算を開始します。")
    result = 10 / 0  # ゼロ除算エラー発生!
except ZeroDivisionError:
    print("【2】エラー:ゼロで割ることはできません。")
finally:
    print("【3】お片付け完了(エラーが起きても必ず実行されます)。")
  • エラーが発生したため except ブロックへワープし、その後逃さずに finally も実行されます。

finallyを使ったファイル処理

ファイルを開いて中身を読み込む際、途中で文字コードエラーなどが起きても、開いたファイルをパソコンのメモリ内に放置せず、確実にクローズ(鍵閉め)する実務のコードです。

# finally を使った安全なファイル閉鎖
try:
    file = open("sample.txt", "r", encoding="utf-8")
    content = file.read() # ここで読み込みエラーが起きる可能性があります
    print(content)
except FileNotFoundError:
    print("ファイルが見つかりませんでした。")
finally:
    # そもそもファイルを開くこと自体に成功し、変数fileが存在している場合のみ閉じます
    if 'file' in locals():
        file.close()
        print("システム:ファイルを安全に閉じました。")

finallyを使ったデータベース処理

データベースの操作中にネットワーク遮断などのエラーが発生しても、サーバーとの接続の結合(セッション)を確実に遮断して、サーバーのパンクを防ぐ書き方です。

# finally を使ったデータベースの接続管理
import sqlite3

try:
    conn = sqlite3.connect("example.db")
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users") # 読み込み処理
    data = cursor.fetchall()
    print(data)
except Exception as e:
    print(f"データベースエラー: {e}")
finally:
    if 'conn' in locals():
        conn.close()
        print("システム:データベース接続を確実に切断しました。")

finallyの注意点

  • 関数内で「return」に出会っても、それを引き留めて実行される:関数の中で try ブロックの内部に return(終了)が書かれていた場合でも、Pythonは関数を終了する直前で一時停止し、finally の中身を先に実行してから、正式に関数から脱出します。
    # returnを追いかけるfinally
    def check_flow():
        try:
            return "tryの戻り値"
        finally:
            print("関数が終了する直前に滑り込みで実行!")
    
    print(check_flow())
    # 出力結果:
    # 関数が終了する直前に滑り込みで実行!
    # tryの戻り値
  • finally の中で「return」を書くのは原則禁止(最重要バグ):もし finally の中に return を書いてしまうと、tryexcept の中で用意されていた本来の return(戻り値)や、キャッチされるはずだったエラーそのものがすべて上書きされて消滅します。
    # 【危険な例】エラーや本来の戻り値を破壊するfinally
    def bad_function():
        try:
            return "正常な結果"
        finally:
            return "finallyのせいで上書きされた結果" # 本来の結果が消えます
    
    print(bad_function()) # 結果: finallyのせいで上書きされた結果

finallyのよくある質問

Q: `finally` の中でさらにエラーが起きた場合はどうなりますか?
A: 残念ながら、finally の中で発生した新しいエラーをキャッチする機構はその場所にはないため、プログラムはその場ですぐにクラッシュしてしまいます。さらに最悪なことに、もし try ブロックで別のエラーが発生していた場合、finally 内の新しいエラーのせいで「元々のエラー原因」が上書きされて画面から消えてしまい、デバッグが極めて困難になります。そのため、finally の中に書くコードは、絶対にエラーが起きない極めてシンプルなクローズ処理だけに絞るのが鉄則です。
Q: ファイル処理の解説でよく見る `with` 構文と `finally` は何が違うのですか?
A: with 構文(コンテキストマネージャ)は、内部的にこの try-finally の「自動クローズ機能」をコンパクトに美しくラッピングしたものです。ファイル操作に関しては、finally を手書きするよりも with 構文を使う方が、コードが短くなり記述ミスも減るため、モダンなPython開発では `with` の使用が強く推奨されています。

# finallyを手書きするより、with構文を使う方がスマートで安全!
with open("sample.txt", "r") as file:
    content = file.read()
# withブロックを抜けた瞬間、エラーの有無に関わらず自動でclose処理が裏で走ります

まとめ

finally は、プログラムがどんな異常事態や早期終了に見舞われようとも、最後に必ず特定の処理を実行させるための、リソース管理の絶対的な防衛ラインです。

  • 正常終了・エラー終了・途中の return にすら関係なく、ブロックの最後で確定で呼び出される。
  • ファイルを開きっぱなしにする、通信を繋ぎっぱなしにする、といったシステムの重大な「リソース漏れ」を防ぐ後片付けに用いる。
  • 内部での return 記述は本来のエラーや計算結果を握りつぶしてしまう致命的なバグに繋がるため、絶対に避ける。

外部のデータベース、API通信、ファイルの入出力など、「プログラムの外の世界」の資源を触るコードを書く場合、この finally(または with 構文)による安全策の確保はプロとして必須のスキルとなります。予期せぬトラブルに強い、頑丈なシステムを構築できるようになりましょう。