[Twisted-Python] deferred object inside function
how can I make a function which have a deferred object return a value that depends of the deferred object's result. example: how can get the result from the resolver? from twisted.names import client, dns def somefunction(somepars): r = client.Resolver('/etc/resolv.conf') d = r.resolve(dns.Query('www.example.com', dns.MX, dns.IN)) d.Callbacks(somefunct1, somefunctErr2) return ? cheers one
Do you want to do something like the following? http://twistedmatrix.com/projects/core/documentation/howto/deferredindepth.h... On Fri, 2006-07-07 at 00:10 -0700, Yusnel Rojas García wrote:
how can I make a function which have a deferred object return a value that depends of the deferred object's result. example: how can get the result from the resolver?
from twisted.names import client, dns
def somefunction(somepars): r = client.Resolver('/etc/resolv.conf') d = r.resolve(dns.Query('www.example.com', dns.MX, dns.IN)) d.Callbacks(somefunct1, somefunctErr2) return ?
cheers one _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
Yusnel Rojas García wrote:
how can I make a function which have a deferred object return a value that depends of the deferred object's result. example: how can get the result from the resolver?
from twisted.names import client, dns
def somefunction(somepars): r = client.Resolver('/etc/resolv.conf') d = r.resolve(dns.Query('www.example.com', dns.MX, dns.IN)) d.Callbacks(somefunct1, somefunctErr2) return ?
Have you read the docs on deferreds? There's a bunch of good ones now, and you can get to them here: http://twistedmatrix.com/projects/core/documentation/howto/index.html In particular, you want the section on "Low-Level Networking and Event Loop". In your example above, you probably want this, instead: d.addCallbacks(yourCallback, yourErrback) As for your question, see if this sums it up: * You want some data * The data depends upon the result If that's correct, then you can only get your data in the callback. Think about writing a class to handle this, and instead of having a function return what you want, you could set a class attribute with the data you're looking for once the callback is fired. Or any other of hundreds of possible solutions ;-) d
Yusnel Rojas García wrote:
how can I make a function which have a deferred object return a value that depends of the deferred object's result. example: how can get the result from the resolver?
from twisted.names import client, dns
def somefunction(somepars): r = client.Resolver('/etc/resolv.conf') d = r.resolve(dns.Query('www.example.com', dns.MX, dns.IN)) d.Callbacks(somefunct1, somefunctErr2) return ?
Have you read the docs on deferreds? There's a bunch of good ones now, and you can get to them here: http://twistedmatrix.com/projects/core/documentation/howto/ index.html
Yes, I think http://twistedmatrix.com/projects/core/documentation/ howto/defer.html is a good place to start also. While I'm no Twisted expert, I think the main point of confusion you are having is here: d.Callbacks(somefunct1, somefunctErr2) return ? The great thing about Deferreds (and Twisted) is that it is asynchronous - that means that calls like your DNS query are non- blocking - in other words, your program doesn't sit around and wait while the DNS query is happening. I think you are expecting your program to wait until the DNS query is finished before getting to the "return" line... but it will keep on going, and later (at some time, maybe a few seconds later) either your "somefunct1" will be called if everything worked out, or your "somefunctErr2" will be called if there is an error. But, it will get to the return line probably before either of those two methods get called. I really do suggest working through the Twisted Howtos (they are *excellent*) and running the example code to see it in action. It helps a lot. Robert
In particular, you want the section on "Low-Level Networking and Event Loop".
In your example above, you probably want this, instead:
d.addCallbacks(yourCallback, yourErrback)
As for your question, see if this sums it up:
* You want some data * The data depends upon the result
If that's correct, then you can only get your data in the callback. Think about writing a class to handle this, and instead of having a function return what you want, you could set a class attribute with the data you're looking for once the callback is fired. Or any other of hundreds of possible solutions ;-)
d
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
Boy no one seemed to offer the answer. What will happen in your code, if I am not mistaken, is that somefunct1() will be called with the results of the resolver. In essense r.resolve() when it returns the deferred promises to invoke one of the callbacks (either the normal one or error one). To that call back it will supply an appropriate argument. You should do a 'return d' from your function. Anyone that issues a Callback against that deferred will be invoked only if your function somefunct() uses the defer. Hope that helps. If not, send me a private email and I can help you get it. Chaz Robert Gravina wrote:
Yusnel Rojas García wrote:
how can I make a function which have a deferred object return a value that depends of the deferred object's result. example: how can get the result from the resolver?
from twisted.names import client, dns
def somefunction(somepars): r = client.Resolver('/etc/resolv.conf') d = r.resolve(dns.Query('www.example.com', dns.MX, dns.IN)) d.Callbacks(somefunct1, somefunctErr2) return ?
Have you read the docs on deferreds? There's a bunch of good ones now, and you can get to them here: http://twistedmatrix.com/projects/core/documentation/howto/index.html
Yes, I think http://twistedmatrix.com/projects/core/documentation/howto/defer.html is a good place to start also.
While I'm no Twisted expert, I think the main point of confusion you are having is here:
d.Callbacks(somefunct1, somefunctErr2) return ?
The great thing about Deferreds (and Twisted) is that it is asynchronous - that means that calls like your DNS query are non-blocking - in other words, your program doesn't sit around and wait while the DNS query is happening. I think you are expecting your program to wait until the DNS query is finished before getting to the "return" line... but it will keep on going, and later (at some time, maybe a few seconds later) either your "somefunct1" will be called if everything worked out, or your "somefunctErr2" will be called if there is an error. But, it will get to the return line probably before either of those two methods get called.
I really do suggest working through the Twisted Howtos (they are *excellent*) and running the example code to see it in action. It helps a lot.
Robert
In particular, you want the section on "Low-Level Networking and Event Loop".
In your example above, you probably want this, instead:
d.addCallbacks(yourCallback, yourErrback)
As for your question, see if this sums it up:
* You want some data * The data depends upon the result
If that's correct, then you can only get your data in the callback. Think about writing a class to handle this, and instead of having a function return what you want, you could set a class attribute with the data you're looking for once the callback is fired. Or any other of hundreds of possible solutions ;-)
d
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
On Fri, 7 Jul 2006 00:10:20 -0700, Yusnel Rojas García <yrojass@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.I... 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-n... 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()
On Fri, 7 Jul 2006 20:18:43 -0400, glyph@divmod.com wrote:
On Fri, 7 Jul 2006 00:10:20 -0700, Yusnel Rojas García <yrojass@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. ^ this comment is incorrect, please ignore it.
participants (6)
-
Chaz.
-
Duncan McGreggor
-
glyph@divmod.com
-
Robert Gravina
-
Thomas Jacob
-
Yusnel Rojas García