[Twisted-Python] deferred object inside function

glyph at divmod.com glyph at divmod.com
Fri Jul 7 20:18:43 EDT 2006


On Fri, 7 Jul 2006 00:10:20 -0700, Yusnel Rojas García <yrojass at gmail.com> wrote:

>from twisted.names import client, dns
>
>def somefunction(somepars):
>       r  = client.Resolver('/etc/resolv.conf')
                             ^ Resolver takes an IP address here,
                               not a filename.
>       d = r.resolve(dns.Query('www.example.com', dns.MX, dns.IN))
              ^ Resolver does not have a "resolve" method.
                You can read the API documentation for IResolver here:
    http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IResolver.html
                Perhaps you meant "lookupMailExchange"?
>       d.Callbacks(somefunct1, somefunctErr2)
          ^ Deferreds do not have this method.
            You can read the API documentation for Deferred here:
   http://twistedmatrix.com/documents/current/api/twisted.internet.defer.html
            Perhaps you meant "addCallbacks"?
>       return ?
               ^ what you want to return here is 'd'
               That way callers of this function can get the results, but they have to wait for the results as well.

The main thing you want to do, e.g. stop your program and wait in-place for results to appear, is completely impossible.  I've watched a number of people go through this process, and I can say with some certainty that what you need to do is focus on understanding why it's impossible, not searching for esoteric ways to make it happen.  If you _do_ manage to do something that appears to be what you want, it will be wrong in surprising and upsetting ways fairly quickly.  If you are just looking for a way to mess around interactively with Deferred objects and their results, run twisted/conch/stdio.py.  Here's a screenshot:

http://twistedmatrix.com/users/glyph/screenshots/twisted-shell-resolving-a-name.png

I've also written a brief example of what you want to do that actually works.  Notice the parts of the code where the result does not exist vs. those where it does.  Keep in mind that *the reactor needs to do work*, such as sending and receiving traffic, in order to produce a result; it's impossible to produce one immediately.

# ---- cut here ----

# We don't need to build queries ourselves, just a resolver.
from twisted.names.client import Resolver

theResolver = Resolver("/etc/resolv.conf")

def getMX(hostname="twistedmatrix.com", r=theResolver):
    d = r.lookupMailExchange(hostname)
    # We're going to look up twistedmatrix.com's address, but we don't have a
    # result *now*...
    def showAddress((answers, authority, additional)):
        # but we _do_ have a result *now*.  the Deferred calls this function
        # when it gets a result, because (see below) ...
        print 'Got', len(answers), 'results.'
        for resourceRecordHeader in answers:
            mxRecord = resourceRecordHeader.payload
            dnsName = mxRecord.name
            nameString = dnsName.name
            print "one answer: ", nameString
        # pass through the values we were given in case callers of this
        # function want to use them.
        return (answers, authority, additional)
    # here we tell the Deferred: when you get a successful result, call that
    # function.
    d.addCallback(showAddress)
    # We return the Deferred so that callers of this function can act upon it.
    return d

from twisted.internet import reactor

# Kick off our code: rather than addCallback, we use addBoth here, because we
# want to stop the reactor whether it fails or not.  If we only wanted to act
# in case the DNS operation failed, we could use addErrback instead.
getMX().addBoth(lambda ignored: reactor.stop())

# You don't have to do this in most Twisted programs, because they will be
# running in the reactor already, and you generally don't want to stop the
# reactor if your program is supposed to keep running.

reactor.run()





More information about the Twisted-Python mailing list