2

ねじれたのは初めてで、延期されたものを試しているところです。100 の遅延呼び出しのリストを構成する次のコードがあります。それぞれがランダムな時間を待機し、値を返します。そのリストは結果を出力し、最後にリアクターを終了します。

しかし、私が原子炉を止める方法はおそらく... 良くないと確信しています。

__author__ = 'Charlie'

from twisted.internet import defer, reactor
import random

def getDummyData(x):
    """returns a deferred object that will have a value in some random seconds
    sets up a callLater on the reactor to trgger the callback of d"""
    d = defer.Deferred()
    pause = random.randint(1,10)
    reactor.callLater(pause, d.callback, (x, pause))
    return d


def printData(result):
    """prints whatever is passed to it"""
    print result


def main():
    """makes a collection of deffered calls and then fires them. Stops reactor at end"""
    deferred_calls = [getDummyData(r) for r in range(0,100)]
    d = defer.gatherResults(deferred_calls, consumeErrors = True)
    d.addCallback(printData)

    # this additional callback on d stops the reacor
    # it fires after all the delayed callbacks have printed their values
    # the lambda ignored: ractor.stop() is required as callback takes a function
    # that takes a parameter.
    d.addCallback(lambda ignored: reactor.stop())

    # start the reactor.
    reactor.run()

if __name__ == "__main__":
    main()

私は、コールバックを追加することによってそれを想定しています:

d.addCallback(lambda ignored: reactor.stop())

収集された結果に実際にそのコールバックをすべての遅延アイテムに追加しますか?

もしそうなら、おそらくもっとエレガントで正しい方法がありますか?

乾杯!

4

1 に答える 1

7

収集された結果にコールバックを追加することにより、実際にそのコールバックがすべての遅延アイテムに追加されると想定していますか?

そうではありません。 新しいgatherResultsを返します。それはあなたが遭遇するかもしれない他のものと同じです。そのメソッドは通常と同じことを行います: 1 つのコールバック チェーンのある時点で呼び出される 1 つの関数を追加します。 DeferredDeferredaddCallback

このようにすべてが素晴らしく規則的で特別でない理由は、すべての入力が結果を持った後に結果を返すという規則的なものだけgatherResultsを与えるために必要なすべてのロジックを処理するためです。DeferredDeferred

gatherResultsそのため、他のDeferred- を返す APIを使用しているように、自由に使用してください。特別じゃない!

そうは言っても、Twisted 12.3 からは、この種の用途に使いたくなる便利なユーティリティがあります - twisted.internet.task.react. これを使用すると、main関数は次のようになります。

def main(reactor):
    """makes a collection of deffered calls and then fires them. Stops reactor at end"""
    deferred_calls = [getDummyData(r) for r in range(0,100)]
    d = defer.gatherResults(deferred_calls, consumeErrors = True)
    d.addCallback(printData)
    return d

if __name__ == "__main__":
    from twisted.internet import task
    task.react(main, [])

getDummyDataまた、グローバル リアクタにも依存しないように変更できることに注意してください。

def getDummyData(reactor, x):
    """returns a deferred object that will have a value in some random seconds
    sets up a callLater on the reactor to trgger the callback of d"""
    d = defer.Deferred()
    pause = random.randint(1,10)
    reactor.callLater(pause, d.callback, (x, pause))
    return d

def main(reactor):
    """makes a collection of deffered calls and then fires them. Stops reactor at end"""
    deferred_calls = [getDummyData(reactor, r) for r in range(0,100)]
    d = defer.gatherResults(deferred_calls, consumeErrors = True)
    d.addCallback(printData)
    return d

twisted.internet.reactorこれで、コードにインポートはまったく必要なくなりました。

twisted.internet.task.deferLaterin を使用しgetDummyDataて、入力をもう少し節約することもできます。

def getDummyData(reactor, x):
    """returns a deferred object that will have a value in some random seconds
    sets up a callLater on the reactor to trgger the callback of d"""
    pause = random.randint(1,10)
    return deferLater(reactor, pause, lambda: (x, pause))
于 2013-11-06T17:22:08.823 に答える