1. ホーム
  2. python

[解決済み] Pythonの例外の連鎖 [重複]について

2023-03-21 11:57:48

質問

Pythonで例外の連鎖を使う標準的な方法はあるのでしょうか? Java の例外 'caused by' のような?

ここにいくつかの背景があります。

1つのメインの例外クラスがあるモジュールを持っています DSError :

 class DSError(Exception):
     pass

このモジュール内のどこかに

try:
    v = my_dict[k]
    something(v)
except KeyError as e:
    raise DSError("no key %s found for %s" % (k, self))
except ValueError as e:
    raise DSError("Bad Value %s found for %s" % (v, self))
except DSError as e:
    raise DSError("%s raised in %s" % (e, self))

基本的にこのスニペットはDSErrorだけを投げて、何が起こったのか、なぜ起こったのかを教えてくれるはずです。 しかし、tryブロックは他の例外をたくさん投げるかもしれないので、次のようなことができればと思います。

try:
    v = my_dict[k]
    something(v)
except Exception as e:
    raise DSError(self, v, e)  # Exception chained...

これはPythonの標準的な方法ですか? 他のモジュールでは例外チェインを見かけなかったので、Pythonではどのように行われているのでしょうか?

どのように解決するのですか?

例外の連鎖 は、Python 3 でしか書けません。

try:
    v = {}['a']
except KeyError as e:
    raise ValueError('failed') from e

のような出力が得られます。

Traceback (most recent call last):
  File "t.py", line 2, in <module>
    v = {}['a']
KeyError: 'a'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "t.py", line 4, in <module>
    raise ValueError('failed') from e
ValueError: failed

たいていの場合、このように from Python 3 はデフォルトで、例外処理中に発生したすべての例外をこのように表示します。

Traceback (most recent call last):
  File "t.py", line 2, in <module>
    v = {}['a']
KeyError: 'a'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "t.py", line 4, in <module>
    raise ValueError('failed')
ValueError: failed

でできること Python 2 のように、例外クラスにカスタム属性を追加することです。

class MyError(Exception):
    def __init__(self, message, cause):
        super(MyError, self).__init__(message + u', caused by ' + repr(cause))
        self.cause = cause

try:
    v = {}['a']
except KeyError as e:
    raise MyError('failed', e)