class SomeError(Exception):
pass
def some_func():
raise SomeError
# 例外クラスを指定しないraise文
try:
# 例外を発生させる可能性があるコード
some_func()
except SomeError as e:
# 例外処理時にその例外を再送出
raise
# raise文に例外クラスを渡す
try:
raise SomeError
except SomeError as e:
print(e)
# raise文に例外クラスのインスタンスを渡す
try:
raise SomeError('sample exception')
except SomeError as e:
print(e) # sample exception
# 例外の連鎖
try:
raise IndexError('occurred in try')
except IndexError as e:
print(e) # occurred in try
raise TypeError('occurred in except')
# 出力結果:
#occurred in try
#Traceback (most recent call last):
# File "<stdin>", line 2, in <module>
#IndexError: occurred in try
#
#During handling of the above exception, another exception occurred:
#
#Traceback (most recent call last):
# File "<stdin>", line 5, in <module>
#TypeError: occurred in except
# 例外の置き換え
try:
raise IndexError('occurred in try')
except IndexError as e:
raise SomeError('occurred in except') from IndexError
# 出力結果:
#IndexError
#
#The above exception was the direct cause of the following exception:
#
#Traceback (most recent call last):
# File "<stdin>", line 4, in <module>
#SomeError: occurred in except
# 例外の置き換えで例外オブジェクトを使用する
try:
raise IndexError('occurred in try')
except IndexError as e:
raise SomeError('occurred in except') from e
# 出力結果:
#Traceback (most recent call last):
# File "<stdin>", line 2, in <module>
#IndexError: occurred in try
#
#The above exception was the direct cause of the following exception:
#
#Traceback (most recent call last):
# File "<stdin>", line 4, in <module>
#SomeError: occurred in except
例外の送出
プログラムの実行時にその場では対処が不可能な状況に陥ったら、そのコードを呼び出した側がその状況に対処することを期待して、例外を送出できる。本稿では以下について紹介する。
- raise文による例外の送出
- ある例外をexcept節で処理している間に新たな例外が発生すると、最初の例外が新しい例外の直接的な原因としてアタッチされる(例外の連鎖)
- raise文にfrom句を付加することで最初の例外を別の例外に置き換えて送出できる
raise文
例外を送出するにはraise文を使用する。raise文には例外クラスやそのインスタンスを渡せる。渡さない場合は、現在処理をしている例外(アクティブな例外)が再送出される。
raise
この書き方は発生した例外を処理している際に、以下のように再度同じ例外を送出するために使われる。
class SomeError(Exception):
pass
def some_func():
raise SomeError
try:
# 例外を発生させる可能性があるコード
some_func()
except SomeError as e:
# 例外処理時にその例外を再送出
raise
他の構文ではraise文に渡せるのは例外クラス、つまりBaseExceptionクラスやその他の例外クラスから派生するクラスだけである。以下に構文を示す。
raise 例外クラス
raise 例外クラス(引数)
次の「raise 例外クラス」はその例外クラスのインスタンスを引数なしで作成したものが呼び出し側へと伝播される。「raise 例外クラス(引数)」は指定した引数で例外クラスのインスタンスを生成し、それが呼び出し側へと伝播される。何らかの情報を例外クラスのインスタンスに付加したいのであれば後者の形を使うことになる。
try:
raise SomeError # 例外クラスを渡す
except SomeError as e:
print(e)
try:
raise SomeError('sample exception') # 例外クラスのインスタンスを渡す
except SomeError as e:
print(e) # sample exception
例外処理の途中で新たな例外が発生した場合、元の例外の情報が新しい例外に原因としてアタッチされる。
try:
raise IndexError('occurred in try')
except IndexError as e:
print(e) # occurred in try
raise TypeError('occurred in except')
# 出力結果:
#occurred in try
#Traceback (most recent call last):
# File "<stdin>", line 2, in <module>
#IndexError: occurred in try
#
#During handling of the above exception, another exception occurred:
#
#Traceback (most recent call last):
# File "<stdin>", line 5, in <module>
#TypeError: occurred in except
上のコード例の上部にあるメッセージから分かるように、アタッチされた例外は例外処理中に発生した例外の原因として呼び出し側に渡される。
これと同様なことをプログラマーの側が明示的に行うことも可能だ。何かの例外が発生して、それを処理する際に例外の置き換えを行いたいときなどに使える。これにはraise文にfrom句を付加する。その構文は以下のようになる(「raise」の直後にある「例外クラス」は「例外クラス」でも「例外クラス(引数)」でも構わない)。
raise 例外クラス from 例外クラス
raise 例外クラス from 例外オブジェクト
「from」に続けて例外クラスを記述した場合はそのクラスのインスタンスが生成され、それが新たに生成する例外(「raise」に続けて記述する例外クラスが表す例外)の原因としてアタッチされる。例外オブジェクトを指定した場合はそれがそのまま原因としてアタッチされる。例外が発生したコンテキストなどの情報が必要であれば、except節で捕捉した例外オブジェクトをfrom句に指定するのがよいだろう。
以下はfrom句で新たに例外クラスのインスタンスを生成している場合だ。
try:
raise IndexError('occurred in try')
except IndexError as e:
raise SomeError('occurred in except') from IndexError
# 出力結果:
#IndexError
#
#The above exception was the direct cause of the following exception:
#
#Traceback (most recent call last):
# File "<stdin>", line 4, in <module>
#SomeError: occurred in except
この場合、IndexError例外の例外を処理中にSomeError例外が発生したことは分かるがもともとの例外の原因に関する情報が失われている。
以下はfrom句に例外オブジェクトを指定した場合の例だ。
try:
raise IndexError('occurred in try')
except IndexError as e:
raise SomeError('occurred in except') from e
# 出力結果:
#Traceback (most recent call last):
# File "<stdin>", line 2, in <module>
#IndexError: occurred in try
#
#The above exception was the direct cause of the following exception:
#
#Traceback (most recent call last):
# File "<stdin>", line 4, in <module>
#SomeError: occurred in except
この場合は、IndexError例外が発生したときのメッセージやトレースバック情報などが新たに発生した例外にアタッチされている。
アプリケーションで独自に例外階層を定義しているような場合、Pythonネイティブな例外が発生したところで、コンテキスト情報を含めたままアプリケーション独自の例外クラスを送出したいといったときに「raise 独自の例外クラス(引数) from 例外オブジェクト」のような書き方をすることで、例外クラスの置き換えができるだろう。
Copyright© Digital Advantage Corp. All Rights Reserved.