1. ホーム
  2. python

[解決済み] 既存の情報を保持したまま、異なる型とメッセージで例外を再提示する。

2022-04-24 10:17:24

質問事項

モジュールを書いていて、そのモジュールが発生させることができる例外の階層を統一したいのですが(例えば FooError 抽象クラスで、すべての foo モジュール固有の例外) を発生させます。これにより、モジュールのユーザはそれらの特定の例外をキャッチし、必要であれば、それらを別個に処理することができます。しかし、モジュールから発生する例外の多くは、他の例外が原因で発生します。例えば、ファイル上のOSErrorが原因でタスクに失敗した場合などです。

必要なのは キャッチした例外を別の型とメッセージを持つように "包む" その情報は、例外をキャッチしたものが伝搬階層のさらに上で利用できるようにするためです。しかし、既存の型、メッセージ、スタックトレースは失いたくありません。これらはすべて、問題をデバッグしようとする人にとって有用な情報です。なぜなら、私は例外が伝搬スタックのさらに上に到達する前に、その例外を装飾しようとしているので、トップレベルの例外ハンドラでは遅すぎるのです。

これは、私のモジュール foo の特定の例外の型は、既存の型(例えば class FooPermissionError(OSError, FooError) ) が、既存の例外インスタンスを新しい型でラップしたり、メッセージを変更したりすることは容易ではありません。

Pythonの PEP 3134 "Exception Chaining and Embedded Tracebacks" は Python 3.0 で受け入れられた、既存の例外の処理中に新しい例外が発生したことを示す "chaining" 例外オブジェクトの変更について議論しています。

私がやろうとしていることは、これに関連しています。私は、以前のバージョンのPythonでも動作する必要があり、連鎖のためではなく、ポリモーフィズムのためだけにそれが必要です。これを行うための正しい方法は何ですか?

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

Python 3 導入 例外の連鎖 (で説明されているように PEP 3134 ). これにより、例外を発生させる際に、既存の例外を「原因」として引き合いに出すことができる。

try:
    frobnicate()
except KeyError as exc:
    raise ValueError("Bad grape") from exc

キャッチした例外( exc これにより、新しい例外であるValueErrorの一部となる(「原因」となる)。この「原因」は、新しい例外をキャッチしたどのコードでも利用可能です。

この機能を利用することで __cause__ 属性が設定されます。また、組み込みの例外ハンドラは は、例外の "原因" と "状況" を報告する方法を知っています。 をトレースバックとともに表示します。


Python 2 で説明されているように、このユースケースには良い答えがないように思われます。 イアン・ビッキング ネッド・バッチェルダー ). ガッカリだ。