Python の例外処理 (try/except/finally)
Python の例外処理の基本 try-except
ここでは Python で例外処理を行う方法を説明します。
「例外とは?」とか「例外処理ハンドラとは?」ということについては、「Python の例外」をみてください。
Python では try ブロックと except ブロックをペアで書きます。
try ブロックには、例外が発生することが想定される処理を書きます。
except ブロックでは、ペアとなっている try ブロックで発生した例外を処理します。
次の例では、try ブロックで foo() という関数を呼び出しています。 ところが、 foo()関数は定義されていないので実行できません。ここで例外が発生します。
try:
foo() # 例外発生!
except:
print('Exception!')
try ブロックを実行中に例外が発生すると、try ブロックに続く except ブロックのステートメントが実行されます。 例外が発生しなければ、except ブロックは実行されません。
except ブロックを例外の型別に書く
未定義の関数を呼び出した時に発生する例外は NameError という型の例外です。
そこで、次の 3 行目のように except ブロックに NameError 型と記載します。すると try ブロックで NameError が発生した時に、この except ブロックが実行されます。
try:
foo()
except NameError: # 処理する例外の型が指定されている
print('Name not defined!') # ここが実行される
except: # NameError 以外はここで処理
print('Unknown exception!')
もし NameError 以外の例外が発生した場合は、もう片方の except ブロックが実行されます。
raise で例外を発生させる
例外は Python の実行環境が発生させるだけではなく、自分で例外を発生させることも可能です。
例外を発生させるためには、 raise キーワードに続けて、例外オブジェクトを書きます。 これによって例外が発生します。
例外は「例外が発生する」という言い方のほか、「例外が投げられる」という言い方をします。「例外」が投げられたら、例外処理ハンドラで例外をキャッチして処理するというイメージです。
例外オブジェクトはビルトインの Exception クラスのオブジェクト、または、その派生クラスのオブジェクトです。上で「例外の型」という言葉が出てきましたが、これは投げた「例外オブジェクトの型」のことです。
Exception クラスのコンストラクタはエラーメッセージを受け取ります。
例外が発生したことによって、try ブロックのステートメントの実行はそこで中断され、例外オブジェクトの型に合う except ブロックのステートメントが実行されます。
try:
raise Exception('my exception')
except:
print('except!')
この例では try ブロックで例外を発生させています。そのため、except ブロックが実行されます。
except で例外オブジェクトを取得する
except に添えた例外の型に続けて、 as <変数> とすることで、 発生した例外オブジェクトを取得することができます。
次の例では、3行目で except NameError as e: とすることで、 NameError 例外が発生したときに変数e に例外オブジェクトがセットされます。
try:
foo()
except NameError as e:
print('Name not defined!')
print(type(e)) # <class 'NameError'>
print(e) # name 'foo' is not defined
except:
print('Unknown exception!')
例外オブジェクトには通常、エラーが発生した理由などが含まれています。
このため例外の詳細情報が取得でき、例外に対してよりきめ細かく対処できるようになります。
except で処理する例外の型は複数指定することができます。
次の例では、NameError、KeyError、Exception の三つの型が指定されています。
try:
foo()
except NameError as e:
print(e)
except KeyError as e:
print('KeyError will be handled here.')
except Exception as e: # これは最後に書く
print('Unknown exception!')
print(e)
発生した例外に固有の例外オブジェクトを取得するためには、なるべく上の方に固有の例外オブジェクトに対する except ブロックを書き、 except Exception as e は最後に書きます。
なぜなら、発生した例外の例外処理ハンドラを探す際には、上から順番に例外の型をチェックするからです。
Exception クラスはエラーを表す全ての例外クラスの親クラスであるため、 もし except Exception as e が先に書いてあると常にマッチしてしまい、特別な例外オブジェクトの型に対する except ブロックが実行されません。
else ブロックは例外が発生しなかったときに実行
except ブロックは、例外が発生したときに実行されるものでした。
else ブロックはその逆で、例外が発生しなかったときにのみ実行されます。
try:
# 何かする
pass
except:
print('An error occurred.') # 例外発生時に実行
else:
print('Everything went ok.') # 例外の発生なし
finally ブロックは例外の発生有無に関わらず常に実行
finally ブロックは例外の発生の有無に関わらず、常に実行されます。
try:
# 何かする
pass
except:
print('An error occurred.') # 例外発生時に実行
else:
print('Everything went ok.') # 例外が発生しなかった時のみ実行
finally:
print('Always executed.') # 常に最後に実行される
例えば、何らかのリソースを解放する処理など、try ブロックでどんな処理をしたにせよ、 最後には必ずチェックしておきたい処理を書くのが finally ブロックです。
以上、Python の例外処理の基本について説明しました。