今回はPythonにおける例外の発生方法と、例外クラスについてまとめました。 以下の記事の続きになります。例外処理がそもそもわからないという方はまずはこちらをどうぞ。
本記事のコードはすべて、Python 3.7.6で実行しています。
例外の発生方法
例えば以下のコードがあったとします。divede()
は、n
÷m
を計算し、オプションパラメータのr
に指定された桁数で丸めて標準出力するといった関数です。
r
に値を入れる場合、0以上の自然数のみ入力を許可し、それ以外の場合は例外を発生させたい場合、以下のようになります。
def divide(n, m, r=None): ans = n / m if r is not None: if not(type(r) == int and r >= 0): raise ValueError('パラメータ:r は0以上の自然数を指定してください') ans = round(ans, r) round print(ans) print('> 100 / 7') divide(100, 7) print('> 100 / 7 (1桁)') divide(100, 7, 1) print('> 100 / 7 (-1桁)') try: divide(100, 7, -1) except Exception as e: print('{}, {}'.format(e.__class__, e)) print('> 100 / 7 (一桁)') try: divide(100, 7, "-1") except Exception as e: print('{}, {}'.format(e.__class__, e))
> 100 / 7 14.285714285714286 > 100 / 7 (1桁) 14.3 > 100 / 7 (-1桁) <class 'ValueError'>, パラメータ:r は0以上の自然数を指定してください > 100 / 7 (一桁) <class 'ValueError'>, パラメータ:r は0以上の自然数を指定してください
5行目のraise ValueError('パラメータ:r は0以上の自然数を指定してください')
で、意図的に例外を発生させています。このように自分で実装したロジック内で例外を発生させ、例外処理を呼び出し元で処理したい場合は、
raise 例外クラス()
と書きます。Javaではこのraiseの部分がthrowで書くので、Javaに親しいエンジニアからは「例外を投げる」って呼ばれることも多いです。
独自例外クラスを定義する
例外を投げるときに、ValueError
などの組み込み例外を利用することができますが、自分で独自例外クラスを定義して例外を投げることもできます。ケースによって例外クラスを使い分けることで、例外処理時に例外クラスで処理を場合分けできます。
class RoundTypeError(Exception): pass class RoundRangeError(Exception): pass def divide(n, m, r=None): MSG = 'パラメータ:r は0以上の自然数を指定してください。' ans = n / m if r is not None: if type(r) != int: raise RoundTypeError(MSG) if r < 0: raise RoundRangeError(MSG) ans = round(ans, r) round print(ans) print('> 100 / 7') divide(100, 7) print('> 100 / 7 (1桁)') divide(100, 7, 1) print('> 100 / 7 (-1桁)') try: divide(100, 7, -1) except Exception as e: print('{}, {}'.format(e.__class__, e)) print('> 100 / 7 (一桁)') try: divide(100, 7, "-1") except Exception as e: print('{}, {}'.format(e.__class__, e))
> 100 / 7 14.285714285714286 > 100 / 7 (1桁) 14.3 > 100 / 7 (-1桁) <class '__main__.RoundRangeError'>, パラメータ:r は0以上の自然数を指定してください。 > 100 / 7 (一桁) <class '__main__.RoundTypeError'>, パラメータ:r は0以上の自然数を指定してください。
RoundTypeError
、RoundRangeError
という2つの例外クラスを定義してみました。それぞれ、Exception
を継承したクラスで、クラス内にはpass
のみを書くことで、実装を省略しています。Exception
を継承することで、raise
で例外を投げることができるようになります。
まとめ
今回は例外を発生させる方法と、独自例外クラスの定義方法についてまとめました。
簡単なサンプルですが、つかみにくい例外、例外処理の理解への一助になればと思います。