Python勉強会@旭川です。もう4回目なんですな。
今回は割と読んだつもりだったのですが、
raiseで例外を送出できるのが、インスタンスだけではなくて、
クラスでもいいってのは見落としていたので、気がつけてよかったです。
というわけで、今日のメモ。
エラーと例外
errorは2つの種類がある。
- 構文エラー
- 例外
構文エラー
pythonを使い始めのころは、インデントがずれてたり、コロンなかったりしてよくSyntaxErrorがでる
例外
例外とは構文上は問題ないが実行中にエラーが発生して処理が止まってしまうあれ。
例えば
- ゼロで割ってしまった。
- 定義していない名前を使った
- 型の異なる(評価する方法がない)オブジェクトを評価してしまった
もうちょいよくありそうなのだと
- ファイルを開こうとしたらファイルがなかった
- ファイルに書き込んだら書き込めなかった。
- メモリを確保しようとしたら足りなかった
- とあるサーバーに接続したかったが繋がらなかった。
というわけで、例外は適当なタイミングで適切に処理しましょう。
例外はtry…exceptで補足することが可能
try:
do_something()
except:
pass # 例外を補足した場合ここを実行
else:
pass # 例外が何も起きなかった場合ここを実行
finally:
pass # 最後に必ず実行
同時に複数の例外を指定することが可能
except (RuntimeError, TypeError, NameError):
pass
exceptでは例外名の後に変数を指定することで、例外インスタンスにアクセスできる。
try:
raise Exception('spam', 'eggs')
except Exception as inst:
print type(inst)
print inst.args
print inst
x, y = inst
print 'x = ', x
print 'y = ', y
<type 'exceptions.Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs
例外の情報はsys.exc_info()でも取得可能
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
ちなみに例外の変数の書き方はいくつか種類がある(あった)。
1. Exception as e
try:
f = open('hogehoge')
except IOError as e:
print e
- Exception, e
たぶんこれは古い書き方・・・だと思う。
try:
f = open('hogehoge')
except IOError, e:
print e
- sys.exc_info()
この場合、[0]がtype, [1]がinstance (exceptions.IOError), [2]にtracebackが格納
try:
f = open('hogehoge')
except IOError:
for e in sys.exc_info():
print type(e)
print e
<type 'type'>
<type 'exceptions.IOError'>
<type 'exceptions.IOError'>
[Errno 2] No such file or directory: 'hoge'
<type 'traceback'>
<traceback object at 0x101f10d88>
- Exception, (errno, msg):
これは1や2と同じだが、ExceptionがErrnoとメッセージのタプルを返すので、
それをそのまま入れている形。
try:
f = open('hogehoge')
except IOError, (errno, msg):
print errno
print msg
例外の送出、再送出
raise文で例外を送出することが可能。
except節の場合、発生している例外を再送出することが可能
try:
raise Exception()
except:
print 'hogehoge'
raise # 再送出 呼び出し側にException()が到達する
raise はクラスでもいい。
でも引数が必要な例外はだめ。
raise Exception
ユーザ定義の例外
通常のクラスの継承と同じで、Exceptionを継承して作ればよい。
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
勉強会では「Exceptionのソースはみてないけどーーー」って話があった気がしますが、
Exceptionのソースはたぶんこれ Python-2.7.3/Objects/exceptions.c
with
ファイルをオープンしたら必ずクローズさせたいときに便利な文
try:
f = open('hoge')
f.read()
finally
f.close()
上の処理が下の処理と同じ感じ
with open('hoge') as f:
f.read()
f.close()は目に見えないけど、裏でやってくれている。
さらに複数の要素も使える。
with A() as a, B() as b:
print a, b
withを作る
withは__enter__()メソッドと__exit__()メソッドを実装していれば使える。
with開始時に__enter__が呼ばれ、その戻り値が渡される。
with文を抜けるときに__exit__が呼ばれる。
class MyClass(object):
def __init__(self, msg):
self.msg = msg
def __enter__(self):
print "enter"
return self
def __exit__(self, exc_type, exc_value, traceback):
print "exit"
print exc_type
print exc_value
print traceback
with MyClass('hogehoge') as m:
print m.msg
enter
hogehoge
exit
None
None
None
次回
さて、次回は私が進行役をやります。
次回はpythonチュートリアルの9.クラスです。
途中から参加でも全然大丈夫ですので、興味のある方は学生さんでも社会人さんでも人妻さんでもどうぞー。