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 の例外処理の基本について説明しました。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Python 入門