2

次のコードを検討してください。

df = defer.Deferred()
def hah(_): raise ValueError("4")
df.addCallback(hah)
df.callback(hah)

実行すると、その例外が食べられます。それはどこに行きましたか?どうすれば表示されるようになりますか? やっdefer.setDebugging(True)ても効果なし。

これを尋ねるのは、「Deferred で未処理のエラー:」という出力が表示されることもあるからです。この場合、どうすればそれを実現できますか?エラーバックを追加するとdf、エラーバックが呼び出されて例外が発生することがわかりますが、エラーを出力して他に何もしたくないので、作成するすべての遅延オブジェクトにそのハンドラーを手動で追加したくありません。

4

1 に答える 1

7

例外はまだ Deferred にあります。この時点で考えられる結果は 2 つあります。

  • Deferred に errback を追加できます。実行するとすぐに、発生した例外を含む Failure で呼び出されます。
  • Deferred をガベージ コレクションにできます (明示的に削除するdfか、関数から戻るか、他の方法で参照を失います)。これにより、「据え置き型の未処理エラー」コードがトリガーされます。

エラーバックはいつでも Deferred に追加できるため (つまり、上記の最初のポイント)、Deferred は、処理されないエラーに対してすぐには何もしません。エラーが本当に未処理なのか、それとも単に未処理なのかはわかりません。Deferred がガベージ コレクションされた場合にのみ、他の誰も例外を処理しないと確信できるため、ログに記録されます。

一般に、Deferred にエラーバックがあることを確認する必要があります。これは、Deferred がいつガベージ コレクションを取得するかを予測するのが難しい場合があるためです。長い時間がかかる可能性があります。つまり、独自のエラーバックが添付されていない場合、例外について知るまでに長い時間がかかる可能性があります。

これはひどい負担である必要はありません。別の Deferred (b) のコールバックから返された Deferred (a) (つまり、チェーンが発生したとき) は、そのエラーを b に渡します。したがって、(a) はログとレポートのために追加のエラーバックを必要としません。(b) のみが必要です。複雑で多くの非同期操作を含む単一の論理タスクがある場合、ほとんどの場合、それらの操作に関与するすべての Deferred は、論理操作を表す 1 つのメインの Deferred に結果 (成功または失敗) を渡す必要があります。多くの場合、その 1 つの Deferred での特別なエラー処理動作のみが必要であり、これにより、関連する他の Deferred からのエラーを処理できます。

于 2010-09-30T13:31:26.027 に答える