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 Deferred
s 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))