こんにちは、吉政創成 菱沼です。
今回もPythonエンジニア育成推進協会のPython 3 エンジニア認定実践試験の主教材「Python実践レシピ/技術評論社」を使って学習中です。
前回は、Pythonが持つ基本的な例外クラスの構造と、それを利用した例外の捕捉方法について学習しました。
今回は、独自で設定できる例外処理について学びます。
Python標準の例外にはない例外を設定したいときはどうすればいいか。
今回はテキストP.43「3.1.3 独自の例外を定義して、例外を送出する」の項目です。
まずは独自の例外について。
Pythonが標準で持っている例外以外に、独自で例外を設定することができるそうです。
設定するにはクラスを使用します。クラスの書き方は別章で学ぶことになるので、ここでは詳細は割愛しますが、基本的な構文は次のような書き方になります。
| class 任意の名前 (Exception): “””独自例外の説明を書く(※書かなくてもいいけどあったら便利)””” Pass |
上記のように書くと、次のような状態になるそうです。
- Exceptionクラスを継承するため、Python標準の一般的な例外(ValueError、TypeError、FileNotFoundErrorなど)と同じくtry-except Exception:で補足できる。
- Exceptionを継承することは必須ではないが、継承しない場合はtry-except Exception:で一般的な例外を補足できず、さらに独自オブジェクトとして通常の例外とは別の扱いになってしまう。
- classに特別な属性やメソッドを持たせず、上記のようにpassとする場合、try-except Exception:で補足することはできるが、個別の独自例外として捕捉する意味はない。
- ただし、将来的に一般的な例外にない個別に捕まえたいエラーが出てきたとき備えて拡張性をもたせる目的で定義だけしておくことができる。
独自のエラーを設定したいときがくるかもしれない。そんなときのために先に準備しておきましょうというときには中身にpassだけを書いておいて、捉まえたい内容がちゃんと決まったときに、きっちりクラスの中身を書きましょう。ということですね。
例外を意図的に発生させてみよう。
では次に例外を意図的に発生させる方法です。
—————————
P.43
3.1.3 独自の例外を定義して、例外を送出する
(中略)
また、raiseキーワードを使用して、例外を意図的に発生させることができます。Exceptionクラスから派生したクラスであれば、独自に定義した例外クラスもraiseキーワードを使用して例外を発生することができます。
—————————
次のような状況で、処理を止めたり、異常を上位に伝えたいときに raise が使用されます。
- 不正な入力値など、想定外のエラーを検知したとき
- 開発・デバッグ中に一時的に処理を止めたいとき
- 異常発生を上位の関数に知らせたいとき
- 独自の例外を発生させたいとき
どのように使用するかは次の通り。
| raise エラー名(“メッセージ”) |
このように書くと、raiseが処理を止めて指定した例外を発生させてくれます。注意点はExceptionのような範囲が広い例外名を指定するのではなく、具体的なエラー名にしてあげないと具体的な原因の特定がしづらくなるため、指定するときは具体的なエラーの名前(例:ValueError、TypeError など)を書いてあげることだとのこと。これによってエラーの内容を明確にしたり、どんな異常が出ているかがわかりやすくなったり、適切なエラー処理がしやすくなります。
独自の例外を作るときの注意点
独自の例外クラスを作る時には、必要な属性だけを定義しておくことで例外が発生したときにエラーに関する情報を取り出せるようにする程度にとどめておくことがポイントだそうです。
テキストに具体例が載っていましたので、引用します。
—————————
P.43、44
3.1.4 例外処理:よくある使い方
(中略)
以下の例では、MyValidateErrorという基底クラスを作成し、それを継承して各検証エラーの例外クラスを定義しています。複数の例外を送出するようなモジュールを作成する際には、そのモジュールで定義されている例外の基底クラスを作成するのが一般的です。MyValidateErrorは、titleとdetailの属性を持ち、詳細なエラー情報を取り出せるようにしています。
—————————
ではこの後に続いているサンプルコードを見てみたいと思います。

それぞれの機能を確認してみたいと思います。
①:Exceptionクラスを継承した独自例外(MyValidateError)
②:MyValidateErrorを継承したサブクラス(MyTypeError / MyMaxError)
→属性(title/detail)は定義しているが、メソッドを追加していないため動作はMyValidateErrorと同じ
③:validate_number()関数で入力値を検証
→文字が入力された場合は ValueError が発生するが、raise によって独自例外 MyTypeError に置き換えて発生
→数値が100を超える場合は MyMaxError を発生
④:try-exceptでMyValidateErrorを指定することで、MyTypeErrorとMyMaxErrorをまとめて捕捉
→発生した例外の内容(title/detail)を表示し、どんなエラーだったかをユーザーに知らせる
というプログラムです。実行結果はこんな感じ。

きりがいいので、今回はこちらで終了です。お付き合いいただきありがとうございました。
実践試験について知りたい方は以下をご覧ください。
●Python3エンジニア認定実践試験

