Deferred オブジェクトの構造
Deferred は一連のペアのコールバック チェーンで構成され、各ペアには成功を処理するためのコールバック (コールバック) とエラーを処理するためのコールバック (エラーバック) が含まれます。最初は、defered は 2 つの空のコールバック チェーンで構成されます。コールバックを追加するときは、常にペアで追加されます。非同期処理の結果が返されると、Deferred が開始され、追加された順序でコールバック チェーンがトリガーされます。
例を使って説明する方が簡単かもしれません。まず、addCallback を見てみましょう:
from twisted.internet.defer import Deferred def myCallback(result): print result d = Deferred() d.addCallback(myCallback) d.callback("Triggering callback.")
これを実行すると、次の結果が得られます:
Triggering callback.
上記の例では、defered が作成され、その addCallback メソッドが作成されます。成功ハンドラーを登録するために使用されます。 d.callback は遅延を開始し、コールバック チェーンを呼び出します。コールバックに渡されるパラメータは、各コールバック チェーンの最初の関数でも受信されます。
addCallback と、もう 1 つの間違ったブランチがありますが、それが addErrorback であることも推測できると思います。例を見てみましょう:
from twisted.internet.defer import Deferred def myErrback(failure): print failure d = Deferred() d.addErrback(myErrback) d.errback(ValueError("Triggering errback."))
それを実行すると、次の結果が得られます:
[Failure instance: Traceback (failure with no frames): <type 'exceptions.ValueError'>: Triggering errback.]
Twisted であることがわかります。 Encapsulated in Failure エラーが削除されます。
前述したように、登録されたコールバックは常にペアであることに注意してください。 d.addCallback メソッドと d.addErrorback メソッドを使用する場合、コールバックまたはエラーバックを追加するだけのようです。実際、このレベルのコールバック チェーンの作成を完了するために、これらのメソッドは残りの半分のパススルーも登録します。コールバック チェーンは常に同じ長さであることに注意してください。このレベルのコールバックのコールバックとエラーバックをそれぞれ指定する場合。 d.addCallbacks メソッドを使用できます:
d = Deferred() d.addCallbacks(myCallback, myErrback) d.callback("Triggering callback.")
それでは...今日はここまでです。
高度な例
次のステップは、より実践的なことを行うことです。それは、Reactor を組み込むことです。まず例を見てみましょう:
from twisted.internet import reactor, defer class HeadlineRetriever(object): def processHeadline(self, headline): if len(headline) > 50: self.d.errback(Exception("The headline ``%s'' is too long!" % (headline,))) else: self.d.callback(headline) def _toHTML(self, result): return "<h1>%s</h1>" % (result,) def getHeadline(self, input): self.d = defer.Deferred() reactor.callLater(1, self.processHeadline, input) self.d.addCallback(self._toHTML) return self.d def printData(result): print result reactor.stop() def printError(failure): print failure reactor.stop() h = HeadlineRetriever() d = h.getHeadline("Breaking News: Twisted Takes us to the Moon!") d.addCallbacks(printData, printError) reactor.run()
上記の例はタイトルを受け取り、それを処理します。タイトルが長すぎる場合は長すぎるエラーが返され、そうでない場合は HTML に変換されて返されます。
指定されたタイトルは 50 文字未満であるため、上記のコードを実行すると次の戻り値が返されます:
<h1>Breaking News: Twisted Takes us to the Moon!</h1>
注目に値する点の 1 つは、上記でリアクターの callLater メソッドが使用されていることです。これは、時間指定されたイベントの作成に使用できます。非同期リクエストをシミュレートします。
たとえば、タイトルを非常に長くすると、次のようになります:
h = HeadlineRetriever() d = h.getHeadline("1234567890"*6) d.addCallbacks(printData, printError)
結果は次のようになります:
[Failure instance: Traceback (failure with no frames): <type 'exceptions.Exception'>: The headline ``123456789012345678901234567890123456789012345678901234567890'' is too long!]
トリガーのプロセスを図で見てみましょう:
Deferreds の重要なポイント
1.コールバックまたはエラーバックが呼び出されたときにトリガーされます。
2. 遅延は 1 回だけトリガーされます。複数回トリガーしようとすると、AlreadyCalledError 例外が発生します。
3. N レベルのコールバックまたはエラーバックの例外は、N+1 レベルのエラーバックに渡されます。 。 N 番目のレベルのコールバックまたはエラーバックが Exception をスローしないか、Failure オブジェクトを返さない場合、コールバックで返された結果は次のレベルのコールバックに渡されます。最初のパラメータ;
5. errback に渡されたエラーが Failure オブジェクトではない場合、自動的に一度ラップされます。