関数内で発生した例外を呼び出し元にも伝える

昨日に続いて例外処理の話です。
ある関数内に、エラーが発生しうる処理がある時、その関数内でtry:〜except:〜処理を書いて
綺麗に例外を処理するけど、その例外を関数の呼び出し元にも伝えて例外を伝播させたいことがあります。

このような時も、 raise 文を使うことができます。

自分は最近まで raise 文は新規に例外を発生させいさせる機能しかないと思ってました。
こういう風に。


raise ValueError

"""
ValueError                                Traceback (most recent call last)
 in ()
----> 1 raise ValueError

ValueError: 
"""

しかし、raiseを単体で使用すると、そのスコープで有効になっている例外を再送出できます。

参考: 7.8. raise 文

試してみる前に、非常に単純な例なのですが次のようなケースを考えてみます。
関数 inv は 引数の逆数を返す関数で、0が渡されたら例外になるはずのものです。
そして、0が渡されたら内部で例外処理をしています。
そして、print_inv は inv を使って、与えられた数の逆数を表示します。


def inv(x):
    try:
        return 1/x
    except Exception as e:
        print(e)


def print_inv(x):
    try:
        print(inv(x))
    except Exception as e:
        print(e)
    else:
        print("print_invで例外は発生しませんでした")


print_inv(0)
"""
division by zero
None
print_invで例外は発生しませんでした
"""

ご覧の通り、 inv 内で例外処理しているので、呼び出し元では例外の発生を検知できていません。

ここで、 raiseを使って例外の再送出を入れてみます。


def inv(x):
    try:
        return 1/x
    except Exception as e:
        print(e)
        # 例外の再送出
        raise


def print_inv(x):
    try:
        print(inv(x))
    except Exception as e:
        print(e)
    else:
        print("print_invで例外は発生しませんでした")


print_inv(0)
"""
division by zero
division by zero
"""

division by zero が 2回表示されました。 inv と print_inv でそれぞれキャッチされた例外です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です