再 raise
この記事は Python Tips Advent Calendar 2012 8日目の記事です。
Python で受けた例外をそのまま上に伝える場合、単に raise と書くだけで伝えられます。
>>> try: #doctest: +ELLIPSIS ... raise Exception, 'error' ... except Exception, e: ... if e.message == 'error': ... raise Traceback (most recent call last): ... Exception: error
これは、以下のように書いたのと同じです。
>>> import sys >>> try: #doctest: +ELLIPSIS ... raise Exception, 'error' ... except Exception, e: ... if e.message == 'error': ... info = sys.exc_info() ... raise info[0], info[1], info[2] Traceback (most recent call last): ... Exception: error
raise の引数はそれぞれ、例外の型を表すオブジェクト、例外オブジェクトに渡す引数、トレースバック情報となります。
単に raise e と思うかもしれませんが、以下のようになってしまいます。
>>> def f3(): ... raise Exception, 'error' >>> def f2(): ... try: ... f3() ... except Exception, e: ... raise e >>> def f1(): ... try: ... f2() ... except Exception, e: ... raise e >>> f1() #doctest: +ELLIPSIS Traceback (most recent call last): File "....py", line 1254, in __run compileflags, 1) in test.globs File "<doctest __main__[3]>", line 1, in <module> f1() File "<doctest __main__[2]>", line 5, in f1 raise e Exception: error
実際に例外を投げたのは f3 関数ですが、トレースバック情報を見てみると、f1 関数で例外が投げられたことになっています。
raise を使えば、
>>> def f3(): ... raise Exception, 'error' ... >>> def f2(): ... try: ... f3() ... except Exception, e: ... raise ... >>> def f1(): ... try: ... f2() ... except Exception, e: ... raise ... >>> f1() #doctest: +ELLIPSIS Traceback (most recent call last): File "....py", line 1254, in __run compileflags, 1) in test.globals File "<doctest __main__[7]>", line 1, in <module> f1() File "<doctest __main__[6]>", line 3, in f1 f2() File "<doctest __main__[5]>", line 3, in f2 f3() File "<doctest __main__[4]>", line 2, in f3 raise Exception, 'error' Exception: error
このように f3 で例外が投げられたことが分かります。
ということで、ちゃんと raise を使う、あるいはトレースバック情報(sys.exc_info()[2])をちゃんと入れるようにしましょう。
.