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

raise で例外を発生させる / 自作例外クラス

Python の raise で例外を発生させる方法と、自作(カスタム)例外クラスの作り方を図解で解説します。実装パターンまで一通り押さえます。

前回try / except では、発生した例外を受け止める側を学びました。

この記事で扱う raise は、自分から例外を発生させる側の書き方です。不正な入力や想定外の状態を検出したときに raise で例外を投げると、呼び出し側が try / except で確実に気づけるようになります。

raise の基本

raise 例外クラス("メッセージ") と書くと、その場で例外を発生させられます。raise が実行された瞬間、以降のコードはスキップされ、対応する except ブロックに処理が飛びます。

メッセージ部分は省略できますが、どんな理由で失敗したかを付けておくと、受け取った側が except ... as e から内容を読み取れます。

raise → except の流れ
try 本体を実行raise ValueError("...")(以降の try 本体はスキップ)except ValueError as ee にメッセージが渡る処理を続行ジャンプ
# raise で ValueError を発生させ、呼び出し側で受け止める
try:
    raise ValueError("年齢が不正です")
    print("ここには到達しない")
except ValueError as e:
    print(f"キャッチ: {e}")
# 出力: キャッチ: 年齢が不正です

# 例外クラスは Python 組み込みのものがそのまま使える
# よく使うもの:ValueError / TypeError / KeyError / IndexError など

raise で例外を投げ、それを try / except で受け止める最小の往復を書きます。

try ブロックの中で raise KeyError("user_id が見つかりません") を実行してください。

except KeyError as e: で例外を受け、「エラー種別: KeyError / 詳細: {e}」と 1 行で表示してください。

try / except の外で print("処理を続行します") を呼び出して、プログラムが止まっていないことを確認してください。

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

Python エディタ

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

if でバリデーションして raise する

raise が最もよく使われるのは、入力値の検査です。if で不正な条件を見つけたら、その場で raise を投げて、呼び出し側に判断を返します。これは後述する関数でよく用いられる手法で、関数の中で引数の不正を検出したときに呼び出し側へ通知する定番のやり方になります。

正常なら普通に処理が流れる、異常なら即 raise で中断するという流れは、実務のバリデーション実装の基本パターンです。

if + raise によるバリデーションの流れ
入力値を受け取る条件1: 値が不正?raise ValueError(...)条件2: 型が不正?raise TypeError(...)正常処理を実行呼び出し側の except が受け止めるYesNoYesNo
# 商品価格のバリデーション:0 以下はエラー扱い
price = -500

try:
    if price < 0:
        raise ValueError(f"価格は 0 以上にしてください(受け取った値: {price})")
    if not isinstance(price, int):
        raise TypeError(f"価格は整数にしてください(受け取った型: {type(price).__name__})")
    print(f"登録完了: {price} 円")
except ValueError as e:
    print(f"値エラー: {e}")
except TypeError as e:
    print(f"型エラー: {e}")
# 出力: 値エラー: 価格は 0 以上にしてください(受け取った値: -500)

組み込み例外の使い分けの目安は次の通りです。値の中身がおかしいなら ValueError、値の種類(型)が想定と違うなら TypeError、辞書やリストに目的のデータが無いなら KeyError / IndexError が自然です。

ユーザー名のバリデーションを書きます。

user_name = "" を定義してください。

try の中で、user_name が空文字列なら raise ValueError("ユーザー名は必須です")len(user_name) > 20 なら raise ValueError("ユーザー名は 20 文字以内です") を投げ、どちらでもなければ「登録完了: {user_name}」と表示してください。

except ValueError as e: でキャッチし、「入力エラー: {e}」を表示してください。

Python エディタ

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

自作例外クラスを定義する

組み込みの例外だけでは「どのバリデーションで落ちたか」が区別しづらいことがあります。そんなときは、自分専用の例外クラスを用意すると、except 側でピンポイントに受け止められるようになります。

作り方は class 例外名(Exception): と書いて、中身は pass(空)にするだけです。class の詳しい話は後のオブジェクト指向の章で扱いますが、例外クラスを作るだけならこの 1 行で十分です。

自作例外クラスの定義と利用
Exception(組み込みの親クラス)class OutOfStockError(Exception): passraise OutOfStockError("在庫切れ")except OutOfStockError as e:e から通知メッセージを取得後続処理を続行親に指定(定義)定義した型を利用
# 独自の例外クラスを定義(1 行で OK)
class InvalidAgeError(Exception):
    pass

class DuplicateUserError(Exception):
    pass

registered_users = ["tanaka", "suzuki"]
new_user = "tanaka"
new_age = -1

try:
    if new_age < 0:
        raise InvalidAgeError(f"年齢は 0 以上: {new_age}")
    if new_user in registered_users:
        raise DuplicateUserError(f"登録済み: {new_user}")
    print(f"登録完了: {new_user}")
except InvalidAgeError as e:
    print(f"年齢エラー: {e}")
except DuplicateUserError as e:
    print(f"重複エラー: {e}")
# 出力: 年齢エラー: 年齢は 0 以上: -1

独自例外は Exception を親クラスに指定する

括弧の中の Exception親となるクラスを指定しています。Exception を親に置くことで、メッセージを保持できる、except Exception でまとめて受け止められる、といった例外の標準機能が自作クラスにも自動で備わります。親子関係(継承)の仕組みそのものはオブジェクト指向の章で詳しく扱いますが、例外を作るだけならこの 1 行で十分です。

在庫切れ専用の独自例外を作って、商品購入処理で投げてみます。

class OutOfStockError(Exception): pass で独自例外を定義してください。

stock = {"apple": 3, "bread": 0}want = "bread" を用意してください。

trystock[want] == 0 のとき raise OutOfStockError(f"在庫切れ: {want}") を投げ、そうでなければ「購入完了: {want}」と表示してください。

except OutOfStockError as e: でキャッチし、「通知: {e}」を表示してください。

Python エディタ

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

この記事では、raise で自分から例外を発生させる方法if + raise を組み合わせたバリデーションパターン、そして Exception を親に指定した自作例外クラスの作り方を学びました。

次の記事では、ここまで何度か顔を出した def を正面から扱い、処理をまとめて再利用する関数を学びます。

QUIZ

理解度チェック

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

Q1次のコードの出力として正しいものはどれですか?
try:
raise ValueError("NG")
print("A")
except ValueError as e:
print(e)
print("B")

Q2値の中身が不正なときに投げる組み込み例外として最も適切なものはどれですか?

Q3自作例外 class MyError(Exception): pass を使う最大のメリットはどれですか?