[Twisted-Python] Re: Making DeferredList look like Deferred

Jean-Paul Calderone exarkun at divmod.com Fri Feb 3 14:08:54 MST 2006 wrote:
...However, if you pass a true value for fireOnOneErrback when constructing your DeferredList, any Deferred which errbacks will cause the DeferredList to errback; in this case it will never callback.
I think I must be missing something, but I can't spot it. Here's the smallest example I've come up with: import random from twisted.internet import reactor, defer from twisted.python import failure def error(err, msg): print "failed: %s" % msg reactor.stop() def success(result, msg): print "succeeded: %s" % msg reactor.stop() def defer2seconds(prob=0.5): d = defer.Deferred() if random.random() < prob: print " deferred will succeed in 2s" reactor.callLater(2, d.callback, True) else: print " deferred will fail in 2s" reactor.callLater(2, d.errback, True) return d def deferlist2seconds(prob=0.25, num=2): def itersuccess(result, i): print " %i succeeded" % i return result def iterfail(err, i): print " %i failed" % i dlist = [] for i in range(num): d = defer2seconds(prob) d.addCallback(itersuccess, i) d.addErrback(iterfail, i) dlist.append(d) dl = defer.DeferredList(dlist, fireOnOneErrback=True) return dl def testdlist(): print "in testdlist" #d = defer2seconds(prob=0.5) d = deferlist2seconds(prob=0.5) d.addCallback(success, "testdlist") d.addErrback(error, "testdlist") if __name__ == "__main__": testdlist() reactor.run() The action here is really simple, with each deferred randomly choosing to succeed or fail. The testdlist function can call either the simple, single-deferred test or the multi-deferredlist test. The goal here is that the caller doesn't care what the underlying function call does, in terms of Deferred v. DeferredList. When calling the simple test, the results are as expected: in testdlist deferred will fail in 2 seconds failed: testdlist in testdlist deferred will succeed in 2 seconds succeeded: testdlist But when calling the DeferredList test, it never gets into the DeferredList's errback. in testdlist deferred will succeed in 2 seconds deferred will succeed in 2 seconds 0 succeeded 1 succeeded succeeded: testdlist in testdlist deferred will fail in 2 seconds deferred will succeed in 2 seconds 0 failed 1 succeeded succeeded: testdlist Why isn't the DeferredList's errback being called in this case? It seems that no matter what I do (remove the individual Deferreds' errbacks, change fireOnOneErrback, etc), the DeferredList's callback only is called. This doesn't sound like what you'd expect. What am I doing wrong? What must I do to get the DeferredList's errback to fire when any single Deferred in the list has its errback called? Tested using twisted 2.1. Thanks, Lenny __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

Quoting Lenny G Arbage <alengarbage@yahoo.com>:
I think I must be missing something, but I can't spot it. Here's the smallest example I've come up with:
[snip]
def iterfail(err, i): print " %i failed" % i
The problem is here. You add an errback to your defer, but you stop the error propagation by not returning err. Either do 'return err' or not 'addErrback(iterfail)'. -- Thomas
participants (2)
-
Lenny G Arbage
-
Thomas HERVE