Python入門:try/except/raise/finallyで学ぶ例外処理

プログラムを実行していると、ファイルが見つからない、ネットワーク接続が失敗する、ユーザー入力が不正など、さまざまなエラー(例外)が発生します。

これらの例外を適切に処理しないと、プログラムは予期せず終了してしまいます。

本記事では、Pythonの例外処理機能として代表的な try / except / raise / finally の使い方を、初心者向けにシンプルかつわかりやすく解説します。


例外処理の概要

例外とは、プログラムの実行中に想定外の事態(エラー)が発生した際に、「通常の処理の流れ」を中断し、エラー情報を呼び出し元や上位の処理に伝える仕組みを指します。

  • 例外(Exception)
    プログラムの実行中に発生するエラー状況を表すオブジェクト
  • 例外処理
    エラーが発生してもプログラムをクラッシュさせず、適切に代替処理や後片付けを行う仕組み

Pythonでは、例外が発生する可能性のあるコードを try ブロック内に書き、その後の処理を except ブロックで補足します。


例外発生の原因例

  • ゼロで割る
  • 数値変換で、数字でない文字を指定
  • 配列の範囲外にアクセス
  • ファイルが存在しない
  • 引数が不正
  • 未定義の変数を呼び出す

try / except の基本構文

except 例外名: で特定の例外を補足します。

どの例外にもマッチさせたい場合は、except Exception:bare except: を利用可能ですが、なるべく具体的な例外を指定するのがベストプラクティスです。

try:
    # 例外が発生する可能性のある処理
    num = int(input("数値を入力してください: "))
    result = 10 / num
    print(f"10 ÷ {num} = {result}")
except ZeroDivisionError:
    # ゼロ除算の例外を補足
    print("0では割り算できません。別の数値を入力してください。")
except ValueError:
    # 整数変換の例外を補足
    print("数値以外が入力されました。整数を入力してください。")

複数の例外をまとめて補足

複数例外をタプルでまとめて指定し、as 変数 で発生した例外オブジェクトを参照できます。

try:
    # ファイルを開いて読み込む
    with open("data.csv", "r", encoding="utf-8") as f:
        data = f.read()
        print(data)
except (FileNotFoundError, PermissionError) as e:
    print(f"ファイルを開けませんでした: {e}")

raise を使った例外の発生(送出)

独自のエラー条件を検出した際に、自ら例外を発生させるには raise を使います。

def divide(a, b):
    if b == 0:
        raise ValueError("b に 0 が指定されました。0 以外の値を指定してください。")
    return a / b

try:
    result = divide(10, 0)
except ValueError as e:
    print(f"エラー: {e}")

raise 例外クラス(“メッセージ”) によって例外を送出できます。


except 内での raise の使い方

except ブロック内でも raise を使って再度例外を送出できます。

try:
    value = int(input("数値を入力: "))
except ValueError as e:
    print("入力が不正です。詳細を表示します。")
    # もとの例外をそのまま再送出
    raise

単に raise と書くと、キャッチした同じ例外をそのまま呼び出し元へ伝搬します。

raise NewException(“説明メッセージ”) from e のように書くと、元の例外をチェインして別の例外を送出できます。


except Exception: と bare except: の使い方

except Exception: は Exception クラスおよびそのサブクラス(ほとんどの例外)をまとめて補足します。

bare except: はシステム退出用の例外(SystemExit、KeyboardInterrupt)なども含め、すべての例外を捕捉してしまいます。

try:
    do_something()
except Exception as e:
    # Exception 系の例外のみ捕捉
    log_error(e)
except:
    # さらに広く、全例外を捕捉(推奨されない)
    print("予期せぬエラーが発生しました。")

一般には、予期しないシステム終了を邪魔しないよう except Exception: を使い、bare except: は可能な限り避けるのが望ましいです。


Exception クラス階層と代表的サブクラス

Python の標準例外はすべて BaseException を頂点(スーパークラス)とした階層を持ち、実際の開発で扱うのはその下位にある Exception のサブクラスです。サブクラスの一例を紹介します。

BaseException
 └─ Exception
     ├─ ArithmeticError
     │   ├─ ZeroDivisionError
     │   └─ OverflowError
     ├─ LookupError
     │   ├─ IndexError
     │   └─ KeyError
     ├─ ValueError
     ├─ TypeError
     ├─ IOError (OSError)
     ├─ FileNotFoundError (OSError)
     └─ RuntimeError

ValueError は Exception のサブクラスであり、数値変換の失敗などを表します。

IndexError(シーケンスの範囲外アクセス)、KeyError(辞書にないキー参照)、TypeError(不適切な型操作)、IOError/OSError(入出力エラー)など、多くの例外が Exception を継承しています。


finally の使い方

try~except の後に finally ブロックを置くと、例外の有無にかかわらず必ず実行される後片付け処理を書けます。

try:
    f = open("log.txt", "a", encoding="utf-8")
    f.write("プログラムを実行しました。\n")
except IOError as e:
    print(f"書き込みエラー: {e}")
finally:
    f.close()
    print("ファイルを閉じました。")

ネットワーク接続の切断やファイルクローズなど、確実に行いたい処理に適しています。


例外処理のベストプラクティス

  1. 具体的な例外をキャッチ
    except Exception: や except: のみを使うと、不具合箇所の特定が難しくなる。
  2. 例外オブジェクトを利用
    as e で取得し、ログ出力やユーザーメッセージに活用。
  3. 不要な try 範囲は小さく
    例外が発生しそうな処理だけを try に含め、どこでエラーが起きたか分かりやすくする。
  4. リソース管理には with 文を活用
    ファイルやネットワークソケットは with open(…) as f: などで自動クローズ。

演習問題

以下の問題に取り組んで、例外処理の理解を深めましょう。

問題1

ユーザーからファイルパスを入力させ、その内容を表示するプログラムを作成してください。

  • ファイルが存在しない場合は「ファイルが見つかりません」と表示。
  • 読み込みエラーが発生した場合は「ファイルを読み込めませんでした」と表示。

問題2

リスト nums = [5, 0, “a”, 10] の要素を順に取り出し、10を各要素で割るプログラムを書いてください。

  • 要素が数値以外(ゼロ除算含む)の場合はスキップし、処理を続行する。

問題3

以下の関数 calculate_score に、引数が 0~100 の範囲外の場合は ValueError を送出するコードを追加してください。

def calculate_score(score):
    # ここに範囲チェックの例外送出を追加
    return f"スコアは {score} 点です"

演習問題の解答例

解答1

path = input("ファイルパスを入力してください: ")
try:
    with open(path, "r", encoding="utf-8") as f:
        print(f.read())
except FileNotFoundError:
    print("ファイルが見つかりません")
except IOError:
    print("ファイルを読み込めませんでした")

解答2

nums = [5, 0, "a", 10]
for x in nums:
    try:
        result = 10 / x
    except ZeroDivisionError:
        print(f"{x} はゼロ除算のためスキップします")
        continue
    except TypeError:
        print(f"{x} は数値ではないためスキップします")
        continue
    print(f"10 ÷ {x} = {result}")

解答3

def calculate_score(score):
    if not (0 <= score <= 100):
        raise ValueError("score は 0 以上 100 以下で指定してください")
    return f"スコアは {score} 点です"

# 使用例
try:
    print(calculate_score(120))
except ValueError as e:
    print(f"エラー: {e}")

まとめ

本記事では、Pythonの例外処理の基礎である try / except / raise / finally の使い方を、初心者向けに解説しました。

except 内での raise、except Exception: と bare except: の違い、そして Exception クラス階層の理解を深めることで、より堅牢なプログラム設計が可能になります。

演習問題に挑戦し、ぜひご自身のコードへ例外処理を取り入れてみてください!