例外
例外を使う理由
- エラー処理
... デフォルトのエラーハンドラでない処理. 無視(pass).
- 事象の通知
... 「成功」を知らせる.
- 特別な場合の処理
... まれにしか起きない条件の処理.
- 一般的でない制御の流れ
... 高水準のgotoとして利用.
例外の基礎
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()が成功する。
演習問題
- oops という関数を作成せよ。この関数を呼び出すと、IndexError 例外が
明示的に起動されるものとする。
次に、try/except 文の内側で oops を呼び出す別な関数を作成し、
このエラーを捕捉せよ。
oops 関数によって起動される例外を IndexError から KeyError へと
変更した場合、どうなるだろうか。
- 関数で教科書とは別に出した、二次方程式の解を返す関数で、
判別式が正の場合と負の場合とを分けただろうか?
if/else を使っていたら、try/except で書き換えてみよ。