【Python】例外をスロー(raise)してエラーを管理する方法を初心者向けに解説
こんにちは、とまだです。
Pythonでコードを書いていて、「あれ?なんでエラーで止まっちゃうの?」と困ったことはありませんか?
実は、適切にエラーを扱えるようになると、プログラムがぐっと丈夫になるんです。
今回は、Pythonの例外処理について、特にraise
を使った例外のスローについて解説します。
例外って何?日常でたとえると...
例外とは、プログラムの実行中に起きる「想定外の出来事」のことです。
日常生活でたとえると、レストランで注文するときを想像してみてください。
通常は「メニューを見る→注文する→料理が来る」という流れですよね。
でも時には...
- 注文した料理が品切れ
- クレジットカードが使えない
- 営業時間外だった
こんな「想定外」が起きることがあります。
プログラムでも同じように、ファイルが見つからない、数値に変換できない、ネットワークに繋がらないなど、様々な「想定外」が発生します。
これらを例外として扱うことで、プログラムを柔軟に制御できるようになるんです。
まずは基本のtry-except構文から
例外処理の基本はtry-except
構文です。
「とりあえず試してみて(try)、ダメだったら別の処理をする(except)」という流れになります。
# ファイルを開く例
try:
with open("recipe.txt", "r") as f:
content = f.read()
print("レシピの内容:", content)
except FileNotFoundError:
print("レシピファイルが見つかりません!")
上記のコードでは、recipe.txt
というファイルを開こうとしています。
もしファイルが存在しなければ、FileNotFoundError
という例外が発生し、except
ブロックの処理が実行されます。
複数の例外をキャッチする
実際の開発では、複数の種類のエラーが起きる可能性があります。
そんなときは、複数のexcept
を使い分けられます。
def calculate_average(numbers_text):
try:
# 文字列を数値のリストに変換
numbers = [int(x) for x in numbers_text.split(",")]
# 平均を計算
average = sum(numbers) / len(numbers)
return average
except ValueError:
print("数値に変換できない値が含まれています")
except ZeroDivisionError:
print("データが空です")
except Exception as e:
print(f"予期しないエラー: {e}")
# 使用例
result1 = calculate_average("10,20,30") # 正常
result2 = calculate_average("10,abc,30") # ValueError
result3 = calculate_average("") # ZeroDivisionError
このように、エラーの種類に応じて適切な対処ができるようになります。
raiseで例外をスローする
ここからが本題です。
自分で意図的に例外を発生させたいときは、raise
キーワードを使います。
料理の例でいうと、「18歳未満にはお酒を提供できません」というルールを設けるようなものです。
def order_alcohol(age):
if age < 18:
raise ValueError("未成年にはお酒を提供できません")
print("ご注文承りました!")
# 使用例
try:
order_alcohol(16)
except ValueError as e:
print(f"エラー: {e}")
なぜ自分で例外を投げるの?
「エラーなんて起きない方がいいのでは?」と思うかもしれません。
でも、明示的に例外をスローすることには大きなメリットがあります。
-
エラーの原因を明確にできる
- 「何が問題だったか」をはっきり伝えられる
-
呼び出し元に判断を委ねられる
- エラーが起きたときの対処法を柔軟に選べる
-
コードの意図を明確にできる
- 「ここは正常じゃない状態」ということが一目でわかる
実践的な例:ユーザー登録システム
実際の開発でよくあるケースを見てみましょう。
ユーザー登録の処理で、様々な検証を行う例です。
class UserRegistrationError(Exception):
"""ユーザー登録に関するカスタム例外"""
pass
def validate_email(email):
"""メールアドレスの検証"""
if "@" not in email:
raise UserRegistrationError("有効なメールアドレスを入力してください")
if email.count("@") != 1:
raise UserRegistrationError("メールアドレスに@が複数含まれています")
def validate_password(password):
"""パスワードの検証"""
if len(password) < 8:
raise UserRegistrationError("パスワードは8文字以上にしてください")
if not any(c.isdigit() for c in password):
raise UserRegistrationError("パスワードには数字を含めてください")
def register_user(email, password):
"""ユーザー登録のメイン処理"""
try:
# 各種検証
validate_email(email)
validate_password(password)
# ここで実際の登録処理(DB保存など)
print(f"ユーザー登録成功: {email}")
return True
except UserRegistrationError as e:
print(f"登録エラー: {e}")
return False
# 使用例
register_user("test@example", "password123") # メールアドレスが不正
register_user("test@example.com", "pass") # パスワードが短い
register_user("test@example.com", "password123") # 成功
カスタム例外のメリット
上記の例ではUserRegistrationError
という独自の例外クラスを作りました。
これにより、以下のメリットがあります。
- エラーの種類が明確になる
- 他のエラーと区別しやすい
- エラーメッセージをカスタマイズできる
finallyで必ず実行する処理
try-except
に加えて、finally
を使うと「エラーが起きても起きなくても必ず実行する処理」を書けます。
ファイルやデータベース接続など、必ず後片付けが必要な場合に便利です。
def process_data(filename):
file = None
try:
file = open(filename, "r")
data = file.read()
# データ処理
result = len(data.split())
print(f"単語数: {result}")
except FileNotFoundError:
print("ファイルが見つかりません")
finally:
# ファイルが開かれていたら必ず閉じる
if file:
file.close()
print("ファイルを閉じました")
# 使用例
process_data("test.txt")
例外処理のベストプラクティス
1. 具体的な例外をキャッチする
# 悪い例:すべての例外をキャッチ
try:
risky_operation()
except: # または except Exception:
pass # 何もしない
# 良い例:具体的な例外をキャッチ
try:
risky_operation()
except ValueError:
handle_value_error()
except KeyError:
handle_key_error()
2. エラーメッセージは分かりやすく
# 悪い例
if price < 0:
raise ValueError("エラー")
# 良い例
if price < 0:
raise ValueError(f"価格は0以上である必要があります。入力値: {price}")
3. 例外の再スロー
場合によっては、例外をキャッチした後、再度スローすることも必要です。
def process_file(filename):
try:
with open(filename) as f:
return f.read()
except FileNotFoundError:
# ログを記録してから再スロー
print(f"ファイル '{filename}' の読み込みに失敗しました")
raise # 元の例外を再スロー
よくあるシーンでの活用例
APIレスポンスの検証
def fetch_user_data(user_id):
# APIからデータを取得(仮想的な例)
response = api.get(f"/users/{user_id}")
if response.status_code == 404:
raise ValueError(f"ユーザーID {user_id} は存在しません")
elif response.status_code != 200:
raise RuntimeError(f"APIエラー: ステータスコード {response.status_code}")
return response.json()
設定値の検証
def configure_app(config):
required_keys = ["database_url", "api_key", "debug_mode"]
for key in required_keys:
if key not in config:
raise KeyError(f"必須の設定項目 '{key}' が見つかりません")
if not config["database_url"].startswith("postgresql://"):
raise ValueError("データベースURLはPostgreSQLである必要があります")
まとめ
Pythonの例外処理は、エラーに強いプログラムを作るための重要な機能です。
特にraise
を使った例外のスローは、以下の場面で活躍します。
- 入力値の検証
- ビジネスルールの実装
- エラーの明確化
- 処理の中断と通知
最初は「エラーを自分で起こすなんて...」と感じるかもしれません。
でも、適切に例外を使うことで、むしろプログラムは安全で使いやすくなります。
まずは簡単な入力チェックから始めて、徐々に例外処理を活用していきましょう。
エラーと上手に付き合えるようになると、プログラミングがもっと楽しくなるはずです!
著者について

とまだ
フルスタックエンジニア
Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。
著者の詳細を見る →