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

Lenny G Arbage alengarbage at yahoo.com
Mon Feb 6 00:43:25 EST 2006


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 




More information about the Twisted-Python mailing list