Pythonのカスタム例外を完全ガイド!初心者でもわかる独自Exceptionクラスの作り方
生徒
「先生、Pythonでエラーが出たときに、自分で好きなメッセージを作ったり、決まった形の例外を作ったりできますか?」
先生
「もちろんできますよ。Pythonでは、カスタム例外と呼ばれる独自のエラークラスを作ることができるんです。」
生徒
「カスタム例外ってどんなときに役立つんですか?普通の例外だけじゃだめなんですか?」
先生
「普通の例外でも十分な場合はあります。でも、大きいプログラムになったり人と共同で作るときは、専用の例外があると原因がすぐに分かるので、とても便利なんです。」
生徒
「なるほど!まずは基本から知りたいです!」
1. Pythonのカスタム例外とは?
Pythonのカスタム例外とは、自分で作成する独自のエラークラスのことです。例えば、資料の入力が間違っているときや、データの形式が想定と違うときなど、特定の状況を分かりやすく伝えるために利用します。大規模なアプリケーションや複雑な処理では、どこで何が原因でエラーになったのかをはっきりさせることがとても重要です。カスタム例外はプログラムの見通しを良くし、保守も簡単になります。
2. カスタム例外を作る基本(独自のExceptionクラス)
Pythonでカスタム例外を作る方法はとてもシンプルです。標準で用意されているExceptionクラスを継承して、自分専用のクラスを作るだけです。名前はエラー内容が想像しやすいようにするのがポイントです。
class InvalidAgeError(Exception):
pass
このように書くと、InvalidAgeErrorという新しい例外が誕生します。これを実際のプログラムで使うと、年齢入力が間違っていることを明確に伝えることができます。
3. カスタム例外を実際に使ってみよう
たとえば、年齢を入力してもらう小さなプログラムを作るとします。数字ではない文字が入ったときや、ありえない数字が入ったときにカスタム例外で知らせてあげるととても分かりやすい動作になります。
class InvalidAgeError(Exception):
def __init__(self, age):
self.age = age
super().__init__(f"{age} は正しい年齢ではありません。")
def check_age(age):
if age < 0 or age > 150:
raise InvalidAgeError(age)
return "年齢は正しく入力されています。"
try:
result = check_age(-5)
print(result)
except InvalidAgeError as e:
print("カスタム例外が発生しました:", e)
カスタム例外が発生しました: -5 は正しい年齢ではありません。
4. try / except / else / finally の流れも理解しよう
例外処理の流れを理解すると、カスタム例外をどこでどのように扱うべきかが自然と分かるようになります。tryは危険な処理を入れる場所、exceptは例外が起きたときの対処、elseは成功したときの処理、finallyは必ず実行する処理をまとめます。
try:
print("データを読み込みます")
except Exception:
print("エラーが発生しました")
else:
print("問題ありませんでした")
finally:
print("処理を終了します")
5. カスタム例外を使うメリット
カスタム例外の大きなメリットは、原因がすぐに分かるという点です。例えば、入力エラー、ネットワークエラー、権限エラーなど、種類ごとにクラスを作っておけば、except文で的確に処理できます。また、ログを記録する際にも、どの種類のエラーが起きたかを分けて保存できるため、後から調査がしやすくなります。
6. 実務でよく使われるカスタム例外の例
実務では、入力のチェック、APIの通信失敗、ファイルの読み取りミスなど、専用の例外があるととても便利です。チーム開発では、例外の名前とルールを統一すると、プログラムの品質が安定し、保守性も大きく向上します。データベース処理でも「データが見つからないエラー」などをカスタム例外化することがよくあります。
7. カスタム例外を階層化して整理する方法
大きなプロジェクトでは、例外を階層化して整理することも重要です。共通の親クラスを作り、その下に細かいエラーを並べることで、ある種類のエラーだけをまとめて捕捉することができます。この仕組みは、後からエラーを増やしたいときにも柔軟に対応できます。
class AppError(Exception):
pass
class DataNotFoundError(AppError):
pass
class PermissionDeniedError(AppError):
pass
このように階層化しておけば、AppErrorをexceptで受け取るだけで共通の処理が可能になります。