[Twisted-Python] Passing extra arguments along callbacks

Jonathan Ballet jon at multani.info
Fri Oct 21 19:32:10 MDT 2011


Hello,

I'm trying to play a little bit with Twisted to discover how it works
and I thought it was a nice exercise with the following case.

I have a list of IP addresses that I want to get the reverse DNS value.
I'm using the answer provided by JP at
http://twistedmatrix.com/pipermail/twisted-python/2004-September/008715.html
to perform the lookup and it's all good.

I'm putting all the results of client.lookupPointer() into a
DeferredList to display the result in order when everything is donew,
which is also working fine. The code looks like this so far:


def resolve(ip):
    ptr = '.'.join(ip.split('.')[::-1]) + '.in-addr.arpa'
    return client.lookupPointer(ptr)

def display_results(result):
    for (succeeded, value) in result:
        if not succeeded:
            print "unknown"
        else:
            (ans, auth, add) = value
            name = ans[0].payload.name
            print name

d = DeferredList([resolve(ip) for ip in IPS],
                  consumeErrors=True).addCallback(display_results)


Now, I would like to have access both to the result of the lookup but
also the original IP address, so that I can print, especially, the
addresses which failed to be resolved.

At first, I added a callback to lookupPointer() like this:

    client.lookupPointer(ptr).addCallback(lambda r: (ip, r))

and it does the job: in display_results(), I now have the IP address and
the result of the lookup.

However, I'm stuck how to do this for the failures: I tried to add an
errback the same way as I added the callback to lookupPointer(), but
then, it seems that DeferredList() sees the result of the errback() as a
ssuccess, so `succeeded` is True and I hav to ressort to a isinstance()
call to compare to see if my item is a Failure exception or not, like
this:


def display_results(result):
    for (succeeded, value) in result:
        ip, answer = result
        if isinstance(answer, twisted.python.failure.Failure):
            succeeded = False
        ...

My question is: is there a simpler way to pass values along the
callbacks?

Side question: why the reactor is not stopped in the final example
below?


Thanks!

 Jonathan

ps: my final try looks like this:


from twisted.internet import reactor
from twisted.internet.defer import DeferredList
from twisted.names import client
import twisted.python.failure


IPS = open('ips.txt').read().split()[0:10]


def display_results(result):
    for (succeeded, value) in result:
        ip, answer = value
        if isinstance(answer, twisted.python.failure.Failure):
            succeeded = False

        if not succeeded:
            name = "(unknown)"
        else:
            (ans, auth, add) = answer
            name = str(ans[0].payload.name)

        print "%16s: %s" % (ip, name)

def resolve(ip):
    ptr = '.'.join(ip.split('.')[::-1]) + '.in-addr.arpa'
    return client.lookupPointer(ptr).\
            addCallback(lambda x: (ip, x)).\
            addErrback(lambda x: (ip, x))

l = [resolve(ip) for ip in IPS]
d = DeferredList( l, consumeErrors=True).\
        addCallback(display_results).\
        addCallback(lambda x: reactor.stop)

reactor.run()




More information about the Twisted-Python mailing list