A Twisted Design Decision
Jean-Paul Calderone
exarkun at divmod.com
Wed Jan 28 11:40:59 EST 2009
On Wed, 28 Jan 2009 08:05:13 -0800 (PST), koranthala <koranthala at gmail.com> wrote:
>On Jan 28, 8:36 pm, Jean-Paul Calderone <exar... at divmod.com> wrote:
>> [snip]
>> Why isn't the return value of protocol.send propagated back to msg.send?
>> It sounds like it should be.
>>
>> Jean-Paul
>
>Thank you very much again Jean-Paul for helping me out.
>I am unable to understand how I will be able to propogate the return
>value of protocol.send to msg.send.
>Maybe I am being foolish - but my understanding is as follows.
>
>In a non-reactor pattern scenario:
>msg_handler.send_message calls msg.send which inturn calls
>protocol.send.
>So, the reply to protocol.send actually goes up the stack till
>msg_handler.send_message wherein I can increment/decrement success/
>failure counter.
>
>In reactor pattern:
>msg_handler.send_message calls msg.send which call protocol.send which
>causes a deferred to be created.
>Now, when the deferred finishes its work, reactor calls the callback
>associated - but the original context (stack etc) is lost.
>Now, the only mechanism of interaction is via the parameters passed in
>the callback.
You can still interact via return values. You should be thinking about
a Deferred in the same way as you think about a function which returns
a result synchronously. The Deferred represents the result, even though
it isn't the result itself (since the result doesn't exist yet). Anything
you would have done by calling a function and then using its return value
you can do by calling a function and then using the Deferred it returns.
I'll try to update the Twisted version of the code you gave previously to
demonstrate this:
class MessageHandler:
def send_message(self):
def handleResult(result):
if result:
self.success += 1
else:
self.failure += 1
if self.execute():
for i in self.msgs:
msg.send().addCallback(handleResult)
class Message:
def send(self):
self.h = h #The message handler object
self.update_data() #The data to be sent is updated here
return self.protocol.send()
class Protocol:
@deferredGenerator
def send(self):
d = waitForDeferred(getPage(url, method, data))
yield d
if page received:
parse page and see parameters
if parameters:
yield True
return
yield False
See how neither the handler nor the message is passed into the protocol.
The result of the Deferred returned by Protocol.send is instead used by
the handler to do something that the handler knows about. The encapsulation
is the same as it was in your original example. The only significant change
is from synchronous return values to Deferred return values.
Jean-Paul
More information about the Python-list
mailing list