閉じる

【Python】例外処理入門|try-exceptを初心者向けに解説

Pythonのプログラムを書いていると、思わぬエラーで突然処理が止まってしまうことがあります。

そんなときに役立つのが「例外処理」です。

本記事では、Python初心者の方を対象に、try-exceptを中心とした例外処理の基本を、図解とサンプルコード付きで丁寧に解説していきます。

Pythonの例外処理とは

例外(Exception)とは何かをわかりやすく解説

プログラムは、基本的に上から下へ順番に命令を実行していきます。

しかし、実行中に想定外の状況が起きることがあります。

例えば、0で割り算をしてしまったり、存在しないファイルを開こうとしてしまうようなケースです。

このように、「プログラムの実行中に起こる異常な状態」をPythonでは例外(Exception)と呼びます。

例外が発生すると、そのままではプログラムはそこで止まり、以降の処理は実行されません。

Pythonには、以下のような代表的な例外が用意されています。

  • ZeroDivisionError: 0で割り算をしたときに発生します。
  • FileNotFoundError: 存在しないファイルを開こうとしたときに発生します。
  • ValueError: 不正な値が渡されたときに発生します。

これらはすべて「例外オブジェクト」として扱われ、後述するtry-except構文で捕まえて処理を分岐させることができます。

エラーと例外の違いを初心者向けに整理

Pythonでプログラムを書いていると、「エラー」という言葉と「例外(Exception)」という言葉がよく登場します。

初心者の方はこの2つの違いが分かりづらいかもしれません。

一般的なイメージとしては、「エラー」は広い意味での「問題全般」を指し、その中でも「実行中に発生して捕まえられるもの」を例外と考えると整理しやすいです。

Pythonでは、例えば次のようなものは「文法エラー」として、プログラムの実行前(コンパイル段階)に検出されます。

Python
# カンマが抜けているので文法エラー(SyntaxError)になります
numbers = [1 2, 3]

このようなSyntaxErrorは、そもそもプログラムが実行に入る前に止められてしまうため、try-exceptで捕まえることはできません。

一方で、以下のようなコードは、文法としては正しいため実行はできますが、実行中に問題が起こります。

Python
x = 10
y = 0
z = x / y  # ZeroDivisionError が実行中に発生

このような「実行時に発生するエラー」をPythonでは例外(Exception)と呼び、try-exceptで扱うことができます。

例外処理を学ぶメリットと必要性

例外処理を学ぶことには、初心者のうちから大きなメリットがあります。

まず、プログラムが途中で落ちるのを防げるという点が重要です。

例えばWebアプリケーションや自動バッチ処理では、ちょっとした例外で全体が止まると大きな問題になります。

例外処理を正しく行えば、エラーが起きても代替処理に切り替えたり、最低限の後始末をして安全に終了できます。

また、原因調査がしやすくなるという点もあります。

例外メッセージやスタックトレースをログに残すことで、あとから「どこで」「なぜ」失敗したのかを追いかけやすくなります。

さらに、ユーザー向けのアプリケーションであれば、ユーザーに分かりやすいメッセージを表示して、操作ミスを丁寧に案内することもできます。

これは、単にプログラムが落ちてしまうよりも、はるかに良いユーザー体験を提供してくれます。

try-exceptの基本構文

try-exceptの書き方と基本的な流れ

Pythonのtry-except構文は、「この部分でエラーが出るかもしれないので、もし出たらこちらの処理を行う」という書き方をする仕組みです。

基本形は次のようになります。

Python
try:
    # 例外が発生するかもしれない処理
    処理1
    処理2
except 例外の種類:
    # 例外が発生したときの処理
    エラー処理

流れとしては、まずtry:のブロックの中が上から順に実行されます。

その途中で指定した種類の例外が発生した場合、tryブロックを中断してexceptブロックへジャンプし、エラー処理を行います。

例外が発生しなければexceptブロックは実行されず、通常通り次の処理へ進みます。

初心者向けシンプルなtry-exceptのコード例

ユーザーから数字を入力してもらい、それを整数に変換する場面を考えてみます。

ユーザーが数字以外の文字を入力した場合、int()への変換で例外が発生します。

これをtry-exceptで処理すると、次のようになります。

Python
# ユーザーに数値入力をお願いし、整数に変換して表示するサンプル

user_input = input("整数を入力してください: ")

try:
    # ユーザー入力を整数に変換(ここで例外が起きる可能性があります)
    number = int(user_input)
    print("あなたが入力した整数は:", number)
except ValueError:
    # 数字に変換できなかった場合の処理
    print("整数ではない値が入力されました。数字だけを入力してください。")

このコードは、ユーザーが123のような数字を入力した場合は正常に整数に変換され、exceptブロックは実行されません。

一方、abcのような文字列を入力した場合はValueErrorが発生し、except ValueError:以下のメッセージが表示されます。

よくあるエラー(TypeErrorやValueError)を例に解説

Pythonで初心者がよく遭遇する代表的な例外にTypeErrorValueErrorがあります。

それぞれの違いをイメージしやすく整理しておきます。

  • TypeErrorは、「型が合わない」ときに発生します。
  • ValueErrorは、「型は合っているが、値が不正」なときに発生します。

次のサンプルで違いを確認してみましょう。

Python
# TypeError と ValueError の違いを確認するサンプル

# TypeError の例: 異なる型同士の足し算
try:
    result = 10 + "20"  # 整数と文字列を足そうとしている
except TypeError as e:
    print("TypeError が発生しました:", e)

# ValueError の例: 型は文字列だが、中身が数値ではない
try:
    value = int("abc")  # 文字列から整数へ変換しようとしているが、中身が数字ではない
except ValueError as e:
    print("ValueError が発生しました:", e)
実行結果
TypeError が発生しました: unsupported operand type(s) for +: 'int' and 'str'
ValueError が発生しました: invalid literal for int() with base 10: 'abc'

このように、「どの種類の例外が起きたか」を正しく理解しておくと、適切なexceptを書くことができます

代表的な例外処理パターン

複数のexceptで例外を分けて処理する方法

一つのtryブロックの中で、発生しうる例外が複数ある場合、それぞれを別々のexceptで処理することができます。

これにより、例外の種類ごとに適切なメッセージや対処を行うことができます。

Python
# 複数の except で例外を分けて処理するサンプル

user_input1 = input("分子となる整数を入力してください: ")
user_input2 = input("分母となる整数を入力してください: ")

try:
    numerator = int(user_input1)   # 整数に変換
    denominator = int(user_input2) # 整数に変換
    result = numerator / denominator
    print("割り算の結果は:", result)
except ValueError:
    # 数字に変換できなかったとき
    print("整数以外の値が入力されました。半角の数字だけを入力してください。")
except ZeroDivisionError:
    # 0で割ろうとしたとき
    print("0で割ることはできません。分母には0以外の数を入力してください。")

このようにexceptを複数並べると、条件分岐(if文)のように例外ごとに処理を分けることができます。

例外クラスをまとめて処理する書き方

例外の種類が複数あるものの、どの例外でも同じ処理でよい場合は、タプルでまとめて1つのexceptに書くことができます。

Python
# 複数の例外クラスを1つの except でまとめて処理するサンプル

data_list = [10, "20", 0]

for item in data_list:
    try:
        # 文字列 "20" のときは ValueError, 0 のときは ZeroDivisionError が発生します
        number = int(item)
        result = 100 / number
        print("100 /", number, "=", result)
    except (ValueError, ZeroDivisionError) as e:
        # どちらの例外でも共通の処理を行う
        print("計算中にエラーが発生しました:", e)

このようにexcept (ValueError, ZeroDivisionError) as e:のように書くことで、指定したどちらの例外もeに格納され、同じ処理で扱うことができます。

elseとfinallyの使い方

try-except構文には、実はelsefinallyという追加のブロックがあります。

それぞれ次のような意味を持ちます。

  • else: 例外が発生しなかった場合にだけ実行される処理
  • finally: 例外の有無に関係なく必ず最後に実行される処理

これらを含めたフル構文は次の通りです。

Python
try:
    # 例外が発生するかもしれない処理
    処理本体
except 例外の種類:
    # 例外が発生したときの処理
    エラー処理
else:
    # 例外が発生しなかったときのみ実行される処理
    正常終了時の処理
finally:
    # 例外の有無に関係なく必ず実行される処理
    後始末の処理

ファイル操作を例に、elsefinallyを使ったサンプルを見てみましょう。

Python
# else と finally の動きを確認するサンプル

try:
    f = open("sample.txt", "r", encoding="utf-8")
    content = f.read()
except FileNotFoundError:
    print("ファイルが見つかりませんでした。")
else:
    # 例外が発生せず、正常に読み込めたときだけ実行
    print("ファイルの中身:")
    print(content)
finally:
    # f が定義されていて、かつ閉じられていないなら閉じる
    try:
        f.close()
        print("ファイルをクローズしました。")
    except NameError:
        # f が定義されていない場合(ファイルオープン前に例外が出た場合)は何もしない
        pass

finallyブロックは、ファイルのクローズやネットワーク接続の切断など、必ず行いたい後始末に使われることが多いです。

例外メッセージを取得する方法

例外が発生したとき、その内容(メッセージ)を取得して表示したい場合には、exceptasを使います。

Python
# 例外メッセージを取得して表示するサンプル

user_input = input("整数を入力してください: ")

try:
    number = int(user_input)
    print("2倍の値は:", number * 2)
except ValueError as e:
    # e に例外オブジェクトが入っています
    print("ValueError が発生しました。詳細メッセージ:", e)
    print("例外の型:", type(e))

実行すると、例えばabcを入力した場合、以下のような出力が得られます。

実行結果
ValueError が発生しました。詳細メッセージ: invalid literal for int() with base 10: 'abc'
例外の型: <class 'ValueError'>

このようにas eで受け取ることで、例外の詳細なメッセージをログに残したり、画面に表示したりできるようになります。

初心者が押さえるべき例外処理のコツ

乱用NGなexcept文と避けるべき書き方

例外処理では、絶対に避けたい書き方があります。

それは、どんな例外も無条件にキャッチして、何もせずに握りつぶしてしまうようなコードです。

Python
# 悪い例 (絶対にマネしない方がよいパターン)

try:
    risky_operation()
except:
    # 何もせずに例外を握りつぶしてしまう
    pass

このような書き方をすると、バグが発生しても何も表示されず、原因調査が極めて困難になります

また、捕まえた例外の種類が分からないため、誤った状態で処理が続いてしまう危険もあります。

初心者のうちは、次のような点を意識すると安全です。

  • 捕まえる例外の種類を明示する(例: except ValueError:)
  • 最低でもログやメッセージを出力する
  • 本当にすべての例外を捕まえる必要がある場合でも、Exceptionを明示し、内容を記録する
Python
# 少なくとも内容を表示・ログ出力するようにする例

try:
    risky_operation()
except Exception as e:
    print("予期せぬエラーが発生しました:", e)
    # 本来はここでログファイルに書き出したりします

「例外は起きてもかまわない」のではなく、「起きたときにどうするかをきちんと決める」という意識が大切です。

Pythonで独自の例外クラスを作る基礎

Pythonでは、自分で例外クラスを定義することもできます。

規模の大きなアプリケーションでは、独自の例外クラスを用意しておくことで、そのアプリ専用のエラー状態を分かりやすく扱えるようになります。

基本的には、Exceptionクラスを継承して新しいクラスを作ります。

Python
# 独自の例外クラスを定義して使うサンプル

class NegativeNumberError(Exception):
    """負の数が入力されたときに使う独自例外クラス"""
    pass


def calculate_square_root(x):
    """x の平方根を計算する関数。負の数の場合は独自例外を投げる"""
    if x < 0:
        # 独自の例外を発生させる
        raise NegativeNumberError(f"負の数 {x} の平方根は計算できません。")
    return x ** 0.5


try:
    value = int(input("平方根を計算したい整数を入力してください: "))
    result = calculate_square_root(value)
    print("平方根は:", result)
except NegativeNumberError as e:
    print("独自例外が発生しました:", e)
except ValueError:
    print("整数として解釈できない値が入力されました。")

このようにすると、負の数が入力された場合だけを特別扱いできるため、エラーの種類に応じた細やかな制御が可能になります。

例外処理を使った安全なファイル操作の例

ファイルの読み書きは、例外処理が特に重要になる代表的な場面です。

ファイルが存在しなかったり、権限がなかったり、読み込み中にエラーが起きたりする可能性があります。

次のサンプルでは、例外処理を使って安全にファイルを読み込む方法を示します。

Python
# 例外処理を使って安全にファイルを操作するサンプル

filename = "data.txt"

try:
    f = open(filename, "r", encoding="utf-8")
    content = f.read()
except FileNotFoundError:
    print(f"ファイル {filename} が見つかりませんでした。")
except PermissionError:
    print(f"ファイル {filename} を読み取る権限がありません。")
else:
    # ファイルが正常に読み込めたときのみ実行
    print("ファイルの内容:")
    print(content)
finally:
    # f が存在していて、まだ閉じていなければ閉じる
    # with構文を使えばさらに安全に書けますが、例外処理の学習のためにあえてこう書いています。
    try:
        f.close()
    except NameError:
        # f が定義されていない場合は何もしない
        pass

実際の開発ではwith構文を使うことで、自動的にファイルをクローズできるようにすることが一般的です。

とはいえ、例外処理の理解を深めるという意味では、「エラーの有無に関係なく後始末をする」というfinallyの役割を意識しておくことが大切です。

デバッグしやすいtry-exceptの書き方のポイント

最後に、初心者の方がデバッグしやすい例外処理を書くためのポイントを整理します。

1つ目は、「tryブロックは最小限にする」ということです。

以下のように、あまりに広い範囲をtryで囲んでしまうと、どの行で例外が発生したのか分かりづらくなります

Python
# あまりよくない例: try 範囲が広すぎる

try:
    step1()
    step2()
    step3()
    step4()
except Exception as e:
    print("どこかでエラーが発生しました:", e)

これを、原因になりそうな箇所ごとに区切って書き直すと、どこで問題が起きたのかが分かりやすくなります。

Python
# デバッグしやすい例: try の範囲をできるだけ狭くする

try:
    step1()
except Exception as e:
    print("step1 でエラーが発生しました:", e)

try:
    step2()
except Exception as e:
    print("step2 でエラーが発生しました:", e)

# 状況に応じて、さらに細かく分けたり、特定の例外だけを捕まえるようにします

2つ目は、「例外発生時の状況をログに残す」ことです。

例えば、処理対象の値やファイル名などが分かると、原因を特定しやすくなります。

Python
# 例外が発生したときに、状況を併せて表示する例

values = ["10", "20", "abc", "40"]

for v in values:
    try:
        n = int(v)
        print("10を", n, "で割ると:", 10 / n)
    except ValueError as e:
        print(f"値 {v} を整数に変換できませんでした:", e)
    except ZeroDivisionError as e:
        print(f"値 {v} によって 0 で割ろうとしました:", e)

このように、「何をしようとして」「どの値で」「どんな例外が起きたのか」を残しておくと、あとから動きを追いかけるときに非常に役立ちます。

まとめ

本記事では、Python初心者向けに例外処理の基本を解説しました。

例外(Exception)とは実行中に発生するエラーの一種であり、try-exceptを使うことで安全に扱えることを学びました。

ValueErrorTypeErrorといった代表的な例外の違い、複数exceptelsefinallyの活用、独自例外クラスの基本、そして「乱用NGな書き方」まで押さえておけば、実務レベルのコードでも安心してエラー対策ができるようになります。

日々のコードで少しずつtry-exceptを取り入れ、デバッグしやすく信頼性の高いプログラム作成に役立ててください。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!