
Table of Contents(目次)
カスタム例外とは何か
Pythonでは、プログラムの途中で何らかの異常が発生したときに「例外(Exception)」という仕組みが使われます。たとえば、ゼロで割ろうとしたり、存在しないファイルを開こうとしたりすると、Pythonは自動的に例外を発生させます。
しかし、現実のプログラム開発では、標準で用意された例外だけでは足りないことがあります。たとえば、「入力データが不正」や「APIの応答が想定外」など、アプリケーション独自のエラーを表現したい場面があるのです。
そのようなときに役立つのがカスタム例外(ユーザー定義例外)です。これは自分で新しい例外クラスを定義して、特定の状況で使えるようにする仕組みです。
クラスについては専用のレクチャーで学習しますが、カスタム例外は基本の形さえ覚えてしまえば使うことができます。まずは、このレクチャーで紹介する最小限のカスタム例外を使用してみてください。
そのうえで、更に詳細なカスタム例外を作りたくなった場合は、クラスについて学び、その後でこのレクチャーに戻ってきていただければと思います。
基本形:最もシンプルなカスタム例外
Pythonのすべての例外は、Exceptionクラスを基礎にしています。したがって、新しい例外を作りたいときは、Exceptionを継承したクラスを定義するだけです。
# カスタム例外の基本形
class MyError(Exception):
pass
# カスタム例外を発生させる
raise MyError('これはカスタム例外の例です。')
実行結果:
Exception has occurred: MyError
これはカスタム例外の例です。
File "C:\xxxxx\sec03_ctrl_flow_exception.py", line 6, in <module>
raise MyError('これはカスタム例外の例です。')
MyError: これはカスタム例外の例です。
このように、MyErrorという独自の例外を作り、raise文で発生させることができます。Pythonの標準例外と同じように、エラーメッセージとともに表示されます。
カスタム例外を捕まえる
カスタム例外も、通常の例外と同じように try / except 構文で捕まえることができます。
class MyError(Exception):
pass
try:
raise MyError('何か問題が発生しました。')
except MyError as e:
print('カスタム例外を捕まえました:', e)
実行結果:
カスタム例外を捕まえました: 何か問題が発生しました。
このように、通常の例外と同じ感覚で自作の例外を処理することができます。
属性を持つカスタム例外
単にメッセージを持たせるだけでなく、エラーに関連する情報(エラーコードや入力値など)を属性として保存しておくこともできます。
class ValidationError(Exception):
def __init__(self, field, message):
self.field = field
self.message = message
super().__init__(f'{field} にエラーがあります: {message}')
# 使用例
try:
raise ValidationError('ユーザー名', '3文字以上で入力してください。')
except ValidationError as e:
print('エラーの発生箇所:', e.field)
print('エラーメッセージ:', e.message)
実行結果:
エラーの発生箇所: ユーザー名
エラーメッセージ: 3文字以上で入力してください。
このようにして、例外に「どの項目でエラーが起きたのか」などの情報を含めることができます。現実のアプリケーション開発ではとてもよく使われるテクニックです。
共通の親クラスを作る
アプリケーションが大きくなってくると、複数の種類のエラーを定義したくなります。たとえば「入力エラー」「データベースエラー」「通信エラー」などです。
そのときに、すべてのカスタム例外の親クラスを1つ作っておくと便利です。これにより、すべてのアプリケーション固有のエラーをまとめて扱うことができます。
# 共通の親クラス
class ProjectError(Exception):
'''アプリケーション固有の例外の基底クラス'''
pass
# 具体的なエラー
class InputError(ProjectError):
pass
class DatabaseError(ProjectError):
pass
try:
raise InputError('入力が不正です。')
except ProjectError as e:
print('共通の親クラスで捕まえました:', e)
実行結果:
共通の親クラスで捕まえました: 入力が不正です。
このように、ProjectErrorを基底クラスにしておくと、後からどんな種類のエラーが増えてもまとめて処理できるようになります。
例外を再スローする(raise文の再利用)
例外を捕まえたあとで、もう一度外側に伝えたいことがあります。これを「再スロー」と呼びます。
class MyError(Exception):
pass
def process():
try:
raise MyError('内部処理で問題が発生しました。')
except MyError as e:
print('内部で例外を捕まえましたが、外に再スローします。')
raise # 例外を再スロー
try:
process()
except MyError as e:
print('外側で再スローされた例外を捕まえました:', e)
実行結果:
内部で例外を捕まえましたが、外に再スローします。
外側で再スローされた例外を捕まえました: 内部処理で問題が発生しました。
このように、内部関数で一度例外を処理しつつ、外に情報を伝えることができます。
カスタム例外を使うメリット
- エラーの意味が明確になる(例:「入力値エラー」と「通信エラー」を区別できる)
- 例外ごとに異なる処理ができる(例:ログを出すか、ユーザーに通知するか)
- コードの可読性と保守性が向上する
- 共通の親クラスで一括処理ができる
これらの利点により、カスタム例外は中規模以上のアプリケーションではほぼ必須といっても過言ではありません。






