stop a twisted reactor after a gatherResults has finished

放肆的年华 提交于 2019-12-07 02:19:25

I'm assuming that by adding a callback: d.addCallback(lambda ignored: reactor.stop()) to the gathered results actually adds that callback on all the deferred items?

This isn't the case. gatherResults returns a new Deferred. It's just like any other Deferred you might come across. Its addCallback method does the same thing as usual: adds one function that will be called at one point in one callback chain.

The reason everything is nice and regular and unspecial like this is that gatherResults takes care of all the logic necessary to only give that regular Deferred that it returns a result after all of the input Deferreds have a result.

So, feel free to use gatherResults just like you're use any other Deferred-returning API. It's not special!

That said, starting with Twisted 12.3 there's a handy utility that you might want to use for this sort of thing - twisted.internet.task.react. Here's what your main function would look like if you used it:

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, [])

And notice that you could change getDummyData so that it doesn't depend on the global reactor either:

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

And now your code does't need any twisted.internet.reactor imports at all.

You could also use twisted.internet.task.deferLater in getDummyData to save a bit more typing:

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))
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!