finallyの概要
| 例外処理後の必須実行処理(後片付けの保証) Python予約語 | ||
|
finally 概要 わかりやすく説明 |
||
|
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を書いてしまうと、tryやexceptの中で用意されていた本来の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 構文)による安全策の確保はプロとして必須のスキルとなります。予期せぬトラブルに強い、頑丈なシステムを構築できるようになりましょう。