順番に読み進めながら学べます

try / except で例外をキャッチする

Python の例外処理 try / except / finally の基本を解説します。エラーを受け止めて処理を続ける書き方を一通り図解で押さえます。

この記事で扱う try / except は、実行中に発生したエラーを受け止めて、プログラムを止めずに処理を続けるための仕組みです。外部からのデータ取得、ユーザー入力の検証、ファイル操作など、失敗が前提の処理に使います。

構文エラーと実行時エラー

Python のエラーは大きく 2 種類あります。構文エラーはコードが Python の文法規則に違反しているときに発生し、プログラムが実行される前に検出されます。一方、実行時エラー(例外)は文法的には正しいものの、実行中に問題に遭遇したときに発生するエラーです。try / except でキャッチできるのは実行時エラーだけです。

構文エラーと実行時エラー
Python のエラー構文エラー(実行前に検出)実行時エラー(実行中に発生)プログラムは起動せずtry でも止められないtry / except で受け止められるコロン・括弧抜け0 除算・範囲外

構文エラーはコードを読み込んだ瞬間に検出されるため、プログラムは一度も実行されません。実行時エラーは行まで到達して初めて発生するため、try / except で受け止められます。

# 構文エラー:コロン抜け。行が実行される前にエラーになる
# if x > 0
#     print("positive")

# 実行時エラー:文法は正しいが実行中に失敗する
x = 100
print(x / 0)   # ZeroDivisionError: division by zero
print("ここには到達しない")

実行時エラーが出ると、その行以降はすべてスキップされます。次のコードを実行すると、最後の print() は呼ばれずに IndexError でプログラムが停止することを確認できます。

# 実行時エラーの確認:try を使わないとプログラムが止まる
numbers = [10, 20, 30]
print(numbers[10])       # IndexError: list index out of range
print("ここには到達しない")
# 出力:
# Traceback (most recent call last):
#   File "...", line 3, in <module>
# IndexError: list index out of range

try / except の基本

try: ブロックに失敗しそうな処理を書き、except エラークラス: ブロックにその失敗を受けたときの処理を書きます

try の中でエラーが起きた瞬間、残りの try 本体はスキップされ、対応する except に処理が飛びます。except の後ろにあるコードは、エラーが起きてもプログラムが止まらずに続きます。

try / except の流れ
try 本体を実行例外が起きたか?例外なし(最後まで実行)例外発生(以降スキップ)except はスキップ一致する except を実行後続の処理を続行NoYes一致

try の本体を実行し、例外が起きなければ except はスキップされ、そのまま後続に進みます。例外が起きた場合は残りの try 本体をスキップして一致する except に飛び、処理後に後続へ進みます。

# try で囲むと、0 除算が起きても処理が止まらない
a = 100
try:
    result = a / 0
    print(result)           # ここは実行されない
except ZeroDivisionError:
    print("0 で割れません")   # ここへ処理が飛ぶ

print("後続の処理")         # try / except の後は必ず実行される
# 出力: 0 で割れません
#       後続の処理

在庫リストから指定番号の商品を取り出そうとして、範囲外を指定した場合に備えます。

stock = [12, 8, 3](各棚の在庫数)を定義してください。

try を使わずに stock[5] を呼ぶと何が起きるか確認します。解答欄ではコメントアウトのまま残しており、コメントを外して実行すると IndexError でプログラムが止まることが分かります。

③ 次は try の中で print(stock[5]) を実行し、except IndexError: で「指定された棚は存在しません」を表示してください。

try / except の後に print("処理を続行します") を書いて、例外後も処理が続いていることを確認してください。

(正しく実行できれば解説が表示されます)

Python エディタ

コードを実行してください

as e で例外オブジェクトを受け取る

except エラークラス as e: と書くと、発生した例外の詳細が e に入りますprint(e) でエラーメッセージを、type(e) でエラーの種類を取り出せます。ログ出力やデバッグの手がかりとして記録しておくと、あとから原因を追いやすくなります。

user_input = "abc"   # 本来は数値のはずが文字列が来た

try:
    value = int(user_input)
except ValueError as e:
    print("入力が数値ではありません")
    print(f"詳細: {e}")
    print(f"種類: {type(e).__name__}")
# 出力: 入力が数値ではありません
#       詳細: invalid literal for int() with base 10: 'abc'
#       種類: ValueError
as e で受け取った例外オブジェクトの使い方
例外発生int("abc")except ValueError as e例外オブジェクト estr(e)→ メッセージtype(e).__name__→ クラス名traceback.format_exc()→ スタックトレース代入

エラーメッセージだけではどこで例外が起きたかが分からないため、デバッグでは import traceback と一緒に使うのが定番です。traceback.format_exc() で例外発生時の呼び出し経路(スタックトレース)を文字列として取り出せるので、ログ出力に残しておくと原因調査が一気に楽になります。

import traceback

try:
    value = int("abc")
except ValueError as e:
    print(f"詳細: {e}")
    print(f"種類: {type(e).__name__}")
    print("--- traceback ---")
    print(traceback.format_exc())
# 出力:
# 詳細: invalid literal for int() with base 10: 'abc'
# 種類: ValueError
# --- traceback ---
# Traceback (most recent call last):
#   File "...", line 4, in <module>
#     value = int("abc")
# ValueError: invalid literal for int() with base 10: 'abc'

ユーザー入力が数値に変換できない場合に、メッセージ・種類・スタックトレースをまとめて表示します。

① 冒頭で import traceback を書き、user_input = "Tokyo" を定義してください。

try の中で int(user_input) を実行し、except ValueError as e: でキャッチしてください。

except ブロックの中で、「メッセージ: {e} / 種類: {type(e).__name__}」を 1 行で表示し、続けて traceback.format_exc() の結果を print() してください。

Python エディタ

コードを実行してください

複数の except と Exception で包括キャッチ

except1 つの try に複数並べて書けます。発生したエラーに最初に一致したブロックが実行されるので、具体的なエラー → 一般的なエラーの順に並べるのが定石です。

すべての実行時エラーの親クラスが Exception で、except Exception as e: と書けば想定外のエラーも含めて何でも受け止められます

具体 → 一般の順で except を並べる
try 本体で例外発生exceptIndexError?IndexError用処理の実行exceptZeroDivisionError?ZeroDivisionError用処理の実行exceptException?想定外の例外の包括キャッチ後続処理の続行一致不一致一致不一致一致
numbers = [10, 20, 30]
index = 1
divisor = 0

try:
    value = numbers[index]
    print(value / divisor)
except IndexError as e:
    print(f"インデックス範囲外: {e}")
except ZeroDivisionError as e:
    print(f"0 で割れません: {e}")
except Exception as e:
    print(f"その他のエラー: {type(e).__name__}: {e}")
# 出力: 0 で割れません: division by zero

Exception を先頭に書かない

Exception はほぼ全ての例外の親なので、先頭に書くと以降の具体的な except が呼ばれなくなります。想定外のエラーだけを吸収する「最後の網」として、いちばん最後に置きましょう。

ユーザーの購入履歴から指定件数分を取り出して合計し、平均を出す処理です。

history = [1200, 800, 1500](購入金額)と take = 10(取り出し件数)を定義してください。

try の中で total = sum(history[:take]) を計算し、avg = total / len(history[:take]) を求めて print(f"平均: {avg}") してください。

except ZeroDivisionError as e: で「データが 0 件です」、except Exception as e: で「想定外: {e}」を表示する包括キャッチを書いてください(今回は実行するとちゃんと平均が出るはずです)。

Python エディタ

コードを実行してください

finally で後処理を必ず実行する

finally: ブロックは、例外が起きても起きなくても必ず実行される後処理の場所です。ファイルや DB 接続のような確実に閉じたいリソースの解放に使います。

else: ブロックは例外が起きなかったときだけ実行されます。使う機会は多くありませんが、「成功した場合のみ後続処理に進む」構成を明示したいときに便利です。

try / except / else / finally の実行順
try 本体を実行例外が起きたか?else ブロック(成功時だけ)except ブロック(例外を処理)finally ブロック(必ず実行)後続の処理を続行No (成功)Yes (失敗)

try を実行した結果、例外が起きなかった場合は else に進み例外が起きた場合は一致する except に進む。いずれの経路でも最後に必ず finally が呼ばれるのがポイント。

# 正常系:else と finally が実行される
a, b = 10, 2
try:
    result = a / b
except ZeroDivisionError:
    print("0 除算を受け止めました")
else:
    print(f"計算成功: {result}")
finally:
    print("後処理を実行")
# 出力: 計算成功: 5.0
#       後処理を実行

print("---")

# エラー系:except と finally が実行される
a, b = 10, 0
try:
    result = a / b
except ZeroDivisionError:
    print("0 除算を受け止めました")
else:
    print(f"計算成功: {result}")
finally:
    print("後処理を実行")
# 出力: 0 除算を受け止めました
#       後処理を実行

API 呼び出しを模した処理で、成功・失敗・後片付けのすべてのパスをログに残します。

user_ids = [101, 102, 103]target = 0 を定義してください。

try の中で user = user_ids[target] を取り出してください(ここではまだ print しません)。

except IndexError: で「対象ユーザーなし」と表示してください。

else:print(f"取得成功: {user}") を表示し、例外が起きなかったときだけ動くことを確認してください。

finally:print("接続を閉じました") と表示し、成功でも失敗でも必ず出ることを確認してください。

Python エディタ

コードを実行してください

この記事では、try / except による例外処理の基本as e による例外情報の取得複数の except と Exception での包括キャッチ、そして finally による後処理を学びました。次の記事では、自分から例外を投げる raise と、自作の例外クラスの作り方を見ていきます。

QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1次のうち構文エラーの例として正しいものはどれですか?

Q2次のコードの出力として正しいものはどれですか?
a = 100
try:
print(a / 0)
except ZeroDivisionError:
print("caught")
print("end")

Q3try / except / else / finally のうち、例外の有無に関わらず必ず実行されるのはどれですか?