例外

例外を使う理由

例外の基礎

try/except/else

try:
    <statements>        # 実行
except <name>:          # 例外 name が発生
    <statements>
except: <name>, <data>: # name に追加の data
    <statements>
else:
    <statements>        # 例外が発生しなかったとき

try/finally

try:
    <statements>
finally:
    <statements>        # 後始末

raise

raise <name>
raise <name>, <data>

デフォルトの動作

bad.pyを実行.
>>> import bad
Traceback (most recent call last):
  File "", line 1, in ?
    import bad
  File "C:\home\papa\lips\prog-method\bad.py", line 7, in ?
    gosouth(1)
  File "C:\home\papa\lips\prog-method\bad.py", line 5, in gosouth
    print gobad(x, 0)
  File "C:\home\papa\lips\prog-method\bad.py", line 2, in gobad
    return x / y
ZeroDivisionError: integer division or modulo by zero
のように例外(エラー)が発生した時点から遡って呼び出していた関数を表示する. (stack trace)

組み込み例外の捕捉

>>> def kaboom(list, n):
	print list[n]

	
>>> try:
	kaboom([0, 1, 2], 3)
except IndexError:
	print 'Hello world!'

	
Hello world!

ユーザ定義の例外の発生と捕捉

>>> MyError = "my error"
>>> def stuff(file):
	raise MyError

>>> file = open('bad.py', 'r')
>>> try:
	stuff(file)
finally:
	file.close()

	
Traceback (most recent call last):
  File "", line 2, in ?
    stuff(file)
  File "", line 2, in stuff
    raise MyError
my error
>>> file.read()
Traceback (most recent call last):
  File "", line 1, in ?
    file.read()
ValueError: I/O operation on closed file
>>> file = open('bad.py', 'r')
>>> stuff(file)
Traceback (most recent call last):
  File "", line 1, in ?
    stuff(file)
  File "", line 2, in stuff
    raise MyError
my error
>>> file.read()
'def gobad(x, y):\n    return x / y\n\ndef gosouth(x):\n    print gobad(x, 0)\n\ngosouth(1)\n'
try/finally を使った最初の例では、エラーの後に file が閉じられているので、 file.read() が失敗するが、2番目のように stuff() を直接呼んだ場合には、 file が開いたままなので、file.read()が成功する。

演習問題

  1. oops という関数を作成せよ。この関数を呼び出すと、IndexError 例外が 明示的に起動されるものとする。 次に、try/except 文の内側で oops を呼び出す別な関数を作成し、 このエラーを捕捉せよ。 oops 関数によって起動される例外を IndexError から KeyError へと 変更した場合、どうなるだろうか。
  2. 関数で教科書とは別に出した、二次方程式の解を返す関数で、 判別式が正の場合と負の場合とを分けただろうか? if/else を使っていたら、try/except で書き換えてみよ。