私はしばしば、いくつかのコレクションを反復処理し、要素を処理して結果を生成するジェネレーターを持っています。要素の処理で例外が発生する場合があります。ジェネレーターを終了せずに、ジェネレーターの呼び出し元でそのようなジェネレーターで発生するそのような例外を処理したいと思います。結局、反復ではなく処理だけが失敗したため、ジェネレーターは次の反復要素を続行できました。状況を表示する例:
def generator():
for element in collection:
yield process(element) # might raise Exception
def caller():
for product in generator():
doSomethingWith(product)
process()
でスローされた例外を処理したいと思いcaller()
ます。残念ながら、 で例外process()
が発生しgenerator()
、ジェネレーターが終了します (ここでもっと複雑なことをしなければ)。したがって、素朴なアプローチは失敗します。
def generator():
for element in collection:
yield process(element) # might raise Exception
def caller():
for product in generator():
try: # wrong place for try, as the loop will already fail
doSomethingWith(product)
except Exception as problem:
handleProblem(problem)
現在、私の作業中の欠陥のあるアプローチは、例外を生成された値として渡すことです。
def generator():
for element in collection:
try:
yield process(element) # might raise Exception
except Exception as problem:
yield problem
def caller():
for yielded in generator():
if isinstance(yielded, Exception):
problem = yielded
handleProblem(problem)
else:
product = yielded
doSomethingWith(product)
これは機能しますが、次のようないくつかの欠点があります
- これは、製品と例外を区別できるという事実に依存します (通常は例外を生成するジェネレーターでは機能しません)。もちろん、ラッピングを使用してそれを解決できます。
- 生成された値 ( ) を受け取った直後に、醜いチェック パターンが必要です
if isinstance(...)
。 - 通常の Python 例外処理を使用しないため、例外の再発生などによって問題が発生する可能性があります (完全にはチェックしていません)。
これに関するより良いアプローチはありますか?特定の例外のみをキャッチする(他の例外をキャッチしない)などの柔軟性を提供するため、使用する代わりに例外を処理するためにtry
/except
パターンを使用することをお勧めします。caller()
if