try(例外処理)
このページでは豊富な例を用いてPythonの例外処理(try,except,else,finally)を学ぶことができます。
前提として、例外とは「プログラミングの実行中に発生するエラー」のことです。 構文エラー(syntax error, parsing error)のことではないので気をつけてください。
Pythonにも他のプログラミング言語と同様に例外処理をする構文が存在します。
代表的な構文はtryとexceptです。
これら2つを使用することで例外を処理し、あとに続く中断することなく処理を実行することができます。
また、elseやfinallyを使用することで、例外が発生しなかった際の処理やクリーンアップ処理(後始末処理)を記述することもできます。
# 記述例
try:
# 例外が発生する可能性のある処理
except 処理する例外(エラー):
# 例外発生時の処理
else:
# 例外が発生しなかった場合の処理
finally:
# 例外の発生に有無関わらず、最後に必ず行いたい処理
TL;DR
基本
# そのままだとエラーが発生し処理が止まる
int('python')
==> ValueError: invalid literal for int() with base 10: 'python'
# 例外処理の構文、tryとexceptを使用してエラー処理する
try:
int('python')
except ValueError:
print('Error')
print('DONE')
==> Error
==> DONE
# エラーが起こらなければexcept節の処理は実行されない
try:
int('1')
except ValueError:
print('Error')
print('DONE')
==> DONE
# ZeroDivisionError(ゼロで割り算すると起こるエラー)を処理する
try:
100 / 0
except ZeroDivisionError:
print('NOT divided by 0.')
==> NOT divided by 0.
発生したエラーオブジェクトの取得
# asをexceptに使用することでエラーオブジェクトを取得することができる
try:
int('python')
except ValueError as err:
print(type(err))
print('---')
print(err)
------------------------------
<class 'ValueError'>
---
invalid literal for int() with base 10: 'python'
------------------------------
関連情報:type(組み込み関数)の使用方法
例外が発生しない場合の処理(else)
# else節の処理はtry節で例外が発生しなかった場合に実行される
try:
int('100')
except ValueError:
print('except process')
else:
print('else process')
==> else process
# 例外が発生した場合はelse節の処理は実行されない
try:
int('python')
except ValueError:
print('except process')
else:
print('else process')
==> except process
最後に必ず実行する処理(finally)
# finally節の処理は例外処理の構文の最後に必ず実行される
# 例外が発生する場合
try:
int('python')
except ValueError:
print('except process')
else:
print('else process')
finally:
print('finally process')
==> except process
==> finally process
# 例外が発生しない場合
try:
int('100')
except ValueError:
print('except process')
else:
print('else process')
finally:
print('finally process')
==> else process
==> finally process
# except節で例外が発生した場合はfinally節が実行されてから例外が再送出される
try:
int('python')
except ValueError:
raise Exception
else:
print('else process')
finally:
print('finally process')
------------------------------
finally process
Traceback (most recent call last):
...
ValueError: invalid literal for int() with base 10: 'python'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
...
...
Exception
------------------------------
複数の例外処理の記述
# 複数の例外が生じる可能性がある場合は、except節を複数記述することができる
list1 = [100, 200, 300]
try:
list1[0]
int('python')
except ValueError:
print('ValueError except process')
except IndexError:
print('IndexError except process')
==> ValueError except process
# IndexErrorの場合
list1 = [100, 200, 300]
try:
list1[100]
int('1')
except ValueError:
print('ValueError except process')
except IndexError:
print('IndexError except process')
==> IndexError except process
例外処理の記述順
class ParentError(Exception):
pass
class ChildError(ParentError):
pass
class GrandChildError(ChildError):
pass
# 派生クラスであれば例外はその節で処理される
try:
raise ChildError
# ChildErrorはParentErrorの派生クラスなのでこの節で処理される
except ParentError:
print('ParentError')
except ChildError:
print('ChildError')
except GrandChildError:
print('GrandChildError')
==> ParentError
# 正確に例外を処理するために、より具体的なエラークラスの順序で記述することが推奨される
try:
raise ChildError
except GrandChildError:
print('GrandChildError')
except ChildError:
print('ChildError')
except ParentError:
print('ParentError')
==> ChildError
すべての例外のキャッチ(非推奨)
# 非推奨
# except節にどのエラークラスも指定しない場合、
# すべてのエラークラスの基底クラスであるBaseExceptionを指定するのと同義になる
try:
raise BaseException
except:
print('***')
==> ***
解説
# 記述例
try:
# 例外が発生する可能性のある処理
except 処理する例外(エラー):
# 例外発生時の処理
else:
# 例外が発生しなかった場合の処理
finally:
# 例外の発生に有無関わらず、最後に必ず行いたい処理
基本
意図しないユーザの入力や、プログラミング実装時のミスで予期せぬエラーが起こる場合があります。 そういったエラーを例外と呼びます。
例外が発生してしまうと処理が中断されたり、システムの異常を適切に検知できない場合があります。
このような事態を避けるため、Pythonには例外処理の機能が実装されています。
具体的にはtry文と呼ばれる構文で例外が発生する可能性がある箇所を囲み、
例外が発生した場合は発生したエラーをexcept節で受け止め、その中に例外発生時の処理を記述します。
exceptのすぐ後には発生したら処理したい例外クラス(エラークラス)を指定します。 記述した例外クラスに発生した例外が当てはまらない場合には、そのexcept節の処理は実行されません。
注意点として、exceptに例外クラスを指定した場合は指定した例外クラス以外に、 その派生クラスも該当のexcept節で処理される点が挙げられます。
# 指定したインデックスが存在しないのでエラー
list1 = [0, 1, 2]
list1[5]
==> IndexError: list index out of range
# 例外処理を実装した場合
list1 = [0, 1, 2]
try:
list1[5]
except IndexError:
print('No such index.')
print('OK')
==> No such index.
==> OK
# 例外処理を実装してエラーが起こらない場合
list1 = [0, 1, 2]
try:
list1[1]
except IndexError:
print('No such index.')
print('OK')
==> OK
発生したエラーオブジェクトの取得
exceptの後ろには処理したい例外クラスを指定しますが、その後ろにas
と変数を記述すると、
except節の中でその変数を用いて発生した例外クラスのオブジェクトにアクセスすることができます。
list1 = [0, 1, 2]
try:
list1[5]
except IndexError as err:
print(type(err))
print('---')
print(err)
------------------------------
<class 'IndexError'>
---
list index out of range
------------------------------
関連情報:type(組み込み関数)の使用方法
例外が発生しない場合の処理(else)
except節以降にelse
節を記述することができます。
このelse節の処理はtry節で例外が発生しなかったときに実行されます。
# try節で例外が発生する場合
dict1 = {'py': 'Python'}
try:
dict1['js']
except KeyError:
print('except process')
else:
print('else process')
==> except process
# try節で例外が発生しない場合
try:
dict1['py']
except KeyError:
print('except process')
else:
print('else process')
==> else process
最後に必ず実行する処理(finally)
except節、もしくはelse節以降にfinally
節を記述することができます。
finally節には通常、クリーンアップ動作を定義します。
クリーンアップ動作とは一連の処理で最後に必ず実行する必要がある動作のことです。
実際の処理では、ファイルを開いて書き込み処理などを行った後の、ファイルを閉じる(外部リソースの開放)処理などを記述したりします。
このfinally節の処理は、例外の処理方法、return文やbreak文などによって実行されるタイミングが異なります。 より詳しい挙動を知る必要がある場合、 公式ドキュメントのクリーンアップ動作を定義する の項を参照してください.
# 例外が発生する場合
dict1 = {'py': 'Python'}
try:
dict1['js']
except KeyError:
print('except process')
else:
print('else process')
finally:
print('finally process')
==> except process
==> finally process
# 例外が発生しない場合
dict1 = {'py': 'Python'}
try:
dict1['py']
except KeyError:
print('except process')
else:
print('else process')
finally:
print('finally process')
==> else process
==> finally process
# except節で例外が発生した場合
try:
dict1['js']
except KeyError:
raise Exception
else:
print('else process')
finally:
print('finally process')
------------------------------
finally process
Traceback (most recent call last):
...
KeyError: 'js'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
...
...
Exception
------------------------------
複数の例外処理の記述
except節は複数記述することが可能です。
try節の中で複数種類の例外が発生する可能性がある場合には、 複数のexcept節を記述し、発生した例外の種類により適切な例外処理を行ってください。
# KeyErrorが発生する場合
dict1 = {'py': 'Python'}
try:
dict1['js']
100 / 10
except KeyError:
print('KeyError except process')
except ZeroDivisionError:
print('ZeroDivisionError except process')
==> KeyError except process
# ZeroDivisionErrorが発生する場合
dict1 = {'py': 'Python'}
try:
dict1['py']
100 / 0
except KeyError:
print('KeyError except process')
except ZeroDivisionError:
print('ZeroDivisionError except process')
==> ZeroDivisionError except process
例外処理の記述順
except節は複数記述することが可能ですが、継承関係のある例外を指定する場合にはその順番に注意指定ください。
exceptに例外クラスを指定すると、その例外クラス以外に派生クラスも該当のexcept節でキャッチします。
そのため、以下のコード例のように継承関係のある例外を複数のexceptに指定する場合には、 より具体性の高い例外クラス(最下層の派生クラス)から先に記述するようにしてください。
class FirstError(Exception):
pass
class SecondError(FirstError):
pass
class ThirdError(SecondError):
pass
# ThirdErrorはFirstErrorの派生クラスなので、FirstErrorのexcept節で処理される
try:
raise ThirdError
except FirstError:
print('FirstError')
except SecondError:
print('SecondError')
except ThirdError:
print('ThirdError')
==> FirstError
# より具体性の高いエラークラス順に記述することが推奨される
try:
raise ThirdError
except ThirdError:
print('ThirdError')
except SecondError:
print('SecondError')
except FirstError:
print('FirstError')
==> ThirdError
すべての例外のキャッチ(非推奨)
except節を例外クラスを指定せずに使用すると、すべての例外クラスの基底クラス(base class)であるBaseException
を指定したことと同意義になります。
実際のプログラムでは例外はできる限り詳細に処理される必要があるため、この記述法は非推奨であることに気をつけてください。
# 非推奨
try:
raise BaseException
except:
print('***')
==> ***