37.例外処理

今までの講義では何度かエラーの表示が出ていたかと思います。

例えば

In [1]:
# リスト型を定義
aqq = [1,2,3]
# インデックスで値を抽出
print(aqq[31])
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-1-4d1059cfba83> in <module>()
      2 aqq = [1,2,3]
      3 # インデックスで値を抽出
----> 4 print(aqq[31])

IndexError: list index out of range

リスト型のインデックスの範囲外の値を指定すると

list index out of range

エラーが発生します、リストの範囲外というエラー出力です。

こういったエラーが発生すると、
そこでプログラムは終了してしまいます。
なのでエラーを発生させないようにするか、
エラーが発生した場合の対処をする必要があります。

エラーの発生を抑えるのは困難なので、
エラーを回避する記述をすることで
プログラムを終了させないようにします。

それが例外処理になります。

pythonの例外処理の書き方

try:
    処理
except:
    例外時の処理

pythonでの例外処理は、
エラーが発生しそうな箇所を
try - exceptという文言で囲みます。

exception というのは例外という意味の英語です。
ぜひ覚えておいてください。

In [2]:
try:
    aqq = [1,2,3]
    # ここでエラーが発生する
    print(aqq[31])
except:
    # エラー発生時にはこちらが呼ばれる
    print('error')
error

エラーが発生した場合の処理を
exceptのブロックに書きます。

エラーが発生しても何も処理をしない場合は
何も書かないと構文エラーになってしまうので
pass と書いておきます。

In [3]:
try:
    aqq = [1,2,3]
    print(aqq[31])
except:
    # 何も処理を書か無いとエラーになる
  File "<ipython-input-3-c85aeb4f8051>", line 5
    # 何も処理を書か無いとエラーになる
                      ^
SyntaxError: unexpected EOF while parsing
In [4]:
try:
    aqq = [1,2,3]
    print(aqq[31])
except:
    # 処理が定まらない時はpassと書いておく
    pass

上記ではエラーが発生したことは確認できますが
何が起こっているのかは分からないです。

なのであらかじめエラーが想定できる場合は
エラーが発生した場合の処理を複数書くことができます。

try:
    処理
except エラー名:
    例外時の処理

In [5]:
try:
    aqq = [1,2,3]
    # ここでIndexエラーが発生する
    print(aqq[31])
except IndexError:
    # ここでIndexエラーをキャッチする
    print('index error')
except Exception:
    print('exception')
index error

except の後にエラー名を書くことで、
該当するエラーが発生した場合の処理を
書き分けることができます。

Indexエラーが発生すると分かっていれば
IndexErrorの部分の処理が実行されることになります。
Exception はすべてのエラーを拾います。

pythonのエラーの種類

ZeroDivisionError

数値を0で割ると発生

In [6]:
1/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-6-05c9758a9c21> in <module>()
----> 1 1/0

ZeroDivisionError: division by zero

NameError

存在しない変数やメソッドを参照しようとすると発生

In [7]:
print(asokokoks)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-7-ed0c4fbe8f44> in <module>()
----> 1 print(asokokoks)

NameError: name 'asokokoks' is not defined

そもそもこれは文法間違いであるので、
try-exceptでは
あまり用いられない使い方です。

KeyError

辞書型のキーがない場合などに発生

In [8]:
d ={1:2,3:4}
print(d[5])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-8-bfd75dce33c0> in <module>()
      1 d ={1:2,3:4}
----> 2 print(d[5])

KeyError: 5

他にもたくさんのエラーが存在します。

pythonの組み込みエラーを表示します。

In [9]:
[i for i in dir(__builtins__) if 'Error' in i]
Out[9]:
['ArithmeticError',
 'AssertionError',
 'AttributeError',
 'BlockingIOError',
 'BrokenPipeError',
 'BufferError',
 'ChildProcessError',
 'ConnectionAbortedError',
 'ConnectionError',
 'ConnectionRefusedError',
 'ConnectionResetError',
 'EOFError',
 'EnvironmentError',
 'FileExistsError',
 'FileNotFoundError',
 'FloatingPointError',
 'IOError',
 'ImportError',
 'IndentationError',
 'IndexError',
 'InterruptedError',
 'IsADirectoryError',
 'KeyError',
 'LookupError',
 'MemoryError',
 'NameError',
 'NotADirectoryError',
 'NotImplementedError',
 'OSError',
 'OverflowError',
 'PermissionError',
 'ProcessLookupError',
 'RecursionError',
 'ReferenceError',
 'RuntimeError',
 'SyntaxError',
 'SystemError',
 'TabError',
 'TimeoutError',
 'TypeError',
 'UnboundLocalError',
 'UnicodeDecodeError',
 'UnicodeEncodeError',
 'UnicodeError',
 'UnicodeTranslateError',
 'ValueError',
 'ZeroDivisionError']

特に発生するエラーがわからない場合は
とりあえずtry - exceptで囲んでおいて、のちに
エラー内容に合わせて処理を追加してゆく、
というのが良いでしょう。

エラーの開始、例外処理はプログラムでは必須になるテクニックなので
必ず覚えておいてください。