[解決!Python]例外を処理するには解決!Python

Pythonではエラーは例外として扱われる。プログラム実行時にtry文を使って例外を処理する基礎をまとめて紹介する。

» 2023年06月06日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

# サンプルとして使用する例外クラスと例外を発生する関数の定義
class SampleError0(Exception):
    pass

class SampleError1(Exception):
    pass

class SampleError2(Exception):
    pass

def raise_exception():
    x = input('input 0 to 2: ')
    if x == '0':
        raise SampleError0('sample error #0')
    elif x == '1':
        raise SampleError1('sample error #1')
    elif x == '2':
        raise SampleError2('sample error #2')
    else:
        pass

# try文の全体構造
try:
    # 例外を発生する可能性のあるコード
    raise_exception()
except SampleError0:
    # 捕捉した例外(ここではSampleError0)を処理
    print('sample error #0 raised')
except SampleError1 as e:
    # 捕捉した例外(ここではSampleError1)を処理
    # 発生した例外についての情報はeから取得できる
    print(e)
# except Exception as e:
#     # 例外が発生したが、それをexcept節で捕捉しないと再送出される
#     print(e)
else:
    # 例外が発生しなかったときに実行される
    print('in else: no exception')
finally:
    # 例外の発生の有無に関係なく例外処理の最後に実行される
    print('in finally')

# シンプルな形:try文のexcept節で例外を捕捉する
try:
    # 例外を発生するかもしれないコード
    raise IndexError('sample exception')
except IndexError as e:
    print(e)

# 複数の例外が発生する可能性がある場合
try:
    raise_exception()
except SampleError0:
    print('sample error #0 raised')
except SampleError1:
    print('sample error #1 raised')
except Exception as e:  # Exceptionクラスで他の例外を全て捕捉
    print(e)

# Exceptionクラスを最初に捕捉してはいけない
try:
    raise_exception()
except Exception as e:  # Exceptionクラスで全ての例外を全て捕捉してしまう
    print(e)
except SampleError0:
    print('sample error #0 raised')
except SampleError1:
    print('sample error #1 raised')

# 複数の例外を1つのexcept節で処理する
try:
    raise_exception()
except (SampleError0, SampleError1) as e:
    print(type(e))
except SampleError2 as e:
    print(type(e))

# 例外処理の最後に何か処理をしたい
try:
    raise_exception()
except SampleError0 as e:
    print(e)
except SampleError1 as e:
    print(e)
except SampleError2 as e:
    print(e)
finally:
    print('exception handling has done')

# try節で例外が発生しなかった場合に何か処理をしたい
try:
    pass
except Exception as e:
    print(e)
else:
    print('no exception raised')
finally:
    print('exception handling has done')


例外処理

 Pythonではプログラムの実行時に発生するエラーを「例外」と呼ぶ。例外はその場で対処することでプログラムの動作を続行できることもあれば、対処は不可能でプログラムの動作を中断させることもある。例外に対処することを「例外処理」といい、Pythonではtry文に例外を発生させる可能性があるコードと、例外が発生した際に行う処理を記述していく。

 なお、本稿では以下のような例外クラス(Exceptionクラスの派生クラス)と例外を発生させる可能性のある関数を定義する。

class SampleError0(Exception):
    pass

class SampleError1(Exception):
    pass

class SampleError2(Exception):
    pass

def raise_exception():
    x = input('input 0 to 2: ')
    if x == '0':
        raise SampleError0('sample error #0')
    elif x == '1':
        raise SampleError1('sample error #1')
    elif x == '2':
        raise SampleError2('sample error #2')
    else:
        pass


 raise_exception関数ではキーボードからの入力を受け取り、その値が'0'、'1'、'2'のいずれかであればSampleError0、SampleError1、SampleError2のいずれかの例外クラスを発生させる。それ以外の値であれば、例外を発生させることなく終了するようになっている。

例外処理の全体構造

 try文での例外処理は次のようになる。

  1. try節に例外を発生させる可能性があるコードを記述する
  2. try節で発生する例外を処理するコードをexcept節で処理する。このときには発生する例外ごとにexcept節を記述することで、プログラム実行時に発生したエラーに個別に対処できるようになる
  3. 例外が発生しなかったときに実行したい処理があればそれをelse節に記述する
  4. 例外の発生の有無に関係なく、例外処理の最後に実行したい処理があればfinally節にそれを記述する
  5. try節で例外が発生しなかった場合、else節もfinally節もなければ、その時点でtry文の実行が終了する
  6. except節で処理されなかった(捕捉されなかった)例外があれば、その例外は再送出される

 コードで概要を示すと次のようになる。

try:
    # 例外を発生する可能性のあるコード
    raise_exception()
except SampleError0:
    # 捕捉した例外(ここではSampleError0)を処理
    print('sample error #0 raised')
except SampleError1 as e:
    # 捕捉した例外(ここではSampleError1)を処理
    # 発生した例外についての情報はeから取得できる
    print(e)
# except Exception as e:
#     # 例外が発生したが、それをexcept節で捕捉しないと再送出される
#     print(e)
else:
    # 例外が発生しなかったときに実行される
    print('in else: no exception')
finally:
    # 例外の発生の有無に関係なく例外処理の最後に実行される
    print('in finally')


 except節では「except 例外クラス:」とその節で処理する例外の種類だけを書いてもよいが(上の例の「except SampleError0:」)、発生した例外についての詳細な情報を必要とするのであれば「except 例外クラス as 例外オブジェクト名:」のようにすることで、try節で発生した例外についての情報を持つ例外オブジェクトを変数に代入できる。これにより、except節の内部でそのオブジェクトを使用できる(上の例の「except SampleError1 as e:」が該当する)。

 この例ではSampleError0例外とSampleError1例外は処理しているが、SampleError2例外を処理するコードがない(「except Exception as e:」節がコメントアウトされていなければそこで処理される)。そのため、raise_exception関数でSampleError2例外が発生するとこのtry文では処理ができず、プログラムの制御においてさらに上位の層へと例外が再送出される。

 例えば、このtry文が何かの関数のコードであれば、その関数を呼び出した側に例外が伝播する。あるいは、これがトップレベルで実行されているのであれば、SampleError2例外が再出された時点でプログラムの実行が中断される。

 以下では例外処理の例を幾つか紹介していこう。

シンプルな形:try文のexcept節で例外を捕捉する

 一番シンプルなのは、単一の例外を捕捉して処理するコードだろう。以下はその例だ。

try:
    raise IndexError('sample exception')
except IndexError as e:
    print(e)  # sample exception


 この例ではtry節でIndexError例外を発生させ、except節ではそれを処理している。except節は「except IndexError as e:」となっているので、その内部では例外オブジェクトeを使用して、例外送出時に設定された「sample exception」を取り出せている。

複数の例外が発生する可能性がある場合

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。