3

ブロック__enter__全体を でラップせずに、コンテキストマネージャーのメソッドで例外をキャッチする方法はありますか?withtry

class TstContx(object):
    def __enter__(self):
        raise Exception("I'd like to catch this exception")
    def __exit__(self, e_typ, e_val, trcbak):
        pass


with TstContx():
    raise Exception("I don't want to catch this exception")
    pass

それ自体で例外をキャッチできることはわかっていますが、ステートメント__enter__()を含む関数からそのエラーにアクセスできますか?with

表面的には、コンテキストマネージャーで例外をキャッチ__enter__()するという質問は同じように見えますが、実際には、ステートメントが囲むブロックとは異なる方法でコードを処理することではなく、確実__exit__に呼び出されるようにすることに関する質問です。__enter__with

...明らかに、動機はより明確になるはずです。ステートメントは、完全に自動化されたプロセスのwithログを設定しています。ロギングが設定される前にプログラムが失敗した場合、ロギングによる通知に頼ることができないため、何か特別なことをしなければなりません。そして、次のように、インデントを追加せずに効果を達成したいと思います。

try:
    with TstContx():
        try:
            print "Do something"
        except Exception:
            print "Here's where I would handle exception generated within the body of the with statement"
except Exception:
    print "Here's where I'd handle an exception that occurs in __enter__ (and I suppose also __exit__)"

try2 つのブロックを使用することのもう 1 つの欠点は、例外を処理__enter__するコードが、ブロックの後続の本体で例外を処理するコードの後に​​来ることwithです。

4

2 に答える 2

0

エラーを個別にチェックするために、このドキュメントの例contextlib.ExitStackで概説されているように使用できます。__enter__

from contextlib import ExitStack

stack = ExitStack()
try:
    stack.enter_context(TstContx())
except Exception:  # `__enter__` produced an exception.
    pass
else:
    with stack:
        ...  # Here goes the body of the `with`.
于 2020-11-04T09:28:04.997 に答える