例外処理(try-except)は、発生したエラーを「捕捉」するための機能ですが、堅牢なプログラムを作成するためには、開発者自身が意図的にエラーを「発生」させなければならない場面があります。
例えば、関数の引数に想定外のデータが渡された場合や、処理をこれ以上続けられない状態になった場合に、それを呼び出し元に通知するためです。
この記事では、raise 文を使用して例外を発生させる方法と、入力値の妥当性確認(バリデーション)への活用方法について解説します。
raise 文の基本構文
例外を発生させるには、raise キーワードの後ろに、発生させたい例外クラスのインスタンスを記述します。通常は、例外クラスのコンストラクタにエラーメッセージとなる文字列を渡します。
構文:
raise 例外クラス("エラーメッセージ")
最も一般的に使われる例外クラスには ValueError(値が不適切)、TypeError(型が不適切)、Exception(汎用的なエラー)などがあります。
実践的な使用例:注文処理のバリデーション
具体的な例として、在庫から商品を注文数分だけ引き落とす関数 process_order を作成します。この関数では、以下の2つの不正なケースに対して例外を発生させます。
- 型エラー (
TypeError): 注文数に整数以外(文字列など)が渡された場合。 - 値エラー (
ValueError): 注文数が0以下の場合、または在庫数を超えている場合。
def process_order(current_stock, order_quantity):
"""
在庫から注文数を引き落とし、残りの在庫数を返す関数
"""
# 1. 型のチェック
# 注文数が整数(int)でない場合は TypeError を発生させる
if not isinstance(order_quantity, int):
raise TypeError(f"注文数は整数で指定してください。受け取った型: {type(order_quantity).__name__}")
# 2. 値のチェック(正の数であるか)
if order_quantity <= 0:
raise ValueError("注文数は1以上である必要があります。")
# 3. 値のチェック(在庫が足りているか)
if current_stock < order_quantity:
raise ValueError(f"在庫が不足しています。(在庫: {current_stock}, 注文: {order_quantity})")
# 全てのチェックを通過した場合のみ計算を行う
remaining_stock = current_stock - order_quantity
return remaining_stock
# --- 実行テスト ---
# 正常なケース
try:
stock = 50
new_stock = process_order(stock, 10)
print(f"注文成功。残り在庫: {new_stock}")
except Exception as e:
print(f"エラー: {e}")
print("-" * 20)
# 異常なケース1: 文字列を渡す
try:
process_order(50, "5個")
except TypeError as e:
print(f"型エラーを捕捉: {e}")
# 異常なケース2: 在庫不足
try:
process_order(50, 100)
except ValueError as e:
print(f"値エラーを捕捉: {e}")
実行結果:
注文成功。残り在庫: 40
--------------------
型エラーを捕捉: 注文数は整数で指定してください。受け取った型: str
値エラーを捕捉: 在庫が不足しています。(在庫: 50, 注文: 100)
なぜ print でエラーを表示するだけでは不十分なのか
エラーが発生した際に、単に print("エラーです") と表示して関数を終了(return)する実装を見かけることがありますが、ライブラリや再利用可能な関数においては推奨されません。
理由は以下の通りです。
- 呼び出し元がエラーに気づけない:
returnで終了すると、プログラムは「正常に終了した」とみなされ、後続の処理が続いてしまいます。 - エラー対応を強制できない:
raiseで例外を発生させれば、呼び出し元はtry-exceptで適切に対処するか、プログラムを停止するかを選択せざるを得なくなります。
適切な例外クラスの選び方
raise する際は、状況に最も適した例外クラスを選ぶことが重要です。
TypeError: データ型が期待するものと異なる場合(例: 数値が必要な場所に文字列が来た)。ValueError: 型は合っているが、値の中身が不適切な場合(例: 正の数が必要な場所にマイナスの値が来た)。FileNotFoundError: ファイルが存在しない場合。NotImplementedError: 未実装の機能を呼び出した場合。
適切なクラスを選ぶことで、呼び出し側が except ValueError: のように特定のエラーだけを狙って捕捉できるようになります。
まとめ
- プログラムの仕様に反する操作が行われた場合は、
raise文を使って能動的に例外を発生させます。 raise 例外クラス("メッセージ")の形式で記述します。- 単にメッセージを表示して終了するのではなく、例外を発生させることで、呼び出し元にエラーハンドリングを委ねることができます。
- 状況に応じて
TypeErrorやValueErrorなどを使い分けることが推奨されます。
