Re: A Twisted Design Decision
On Jan 27, 9:27 pm, koranthala koranth...@gmail.com wrote: On Jan 27, 6:57 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Tue, 27 Jan 2009 05:46:25 -0800 (PST), koranthala koranth...@gmail.com wrote: Twisted, being twisted in its behavior is causing quite a lot of confusion in design decisions. I'm not sure I agree with your premise. ;) I will put forward a comparison of reactor and non-reactor patterns. The code is not exact - whatever is shown is the gist of it. For example, a message handler - in a usual scenario: class messageHandler: def run(): msg = self.get_next_msg() if not msg.send(): self.handle_failure() To handle parallel execution, we will have to use threads, but the code flow is similar. How do we do the same in a reactor pattern (Twisted)? msg.send will cause a deferred to be raised - the failure, if it happens will happen much later. i.e. other than sending messageHandler object in msg.send(), I cannot see any mechanism of running handle_failure. In Twisted: class messageHandler: def run(): msg = self.get_next_msg() msg.send(self): class msgClass: def send(o): d = deferred.addCallBack(success_handler, o).addErrBack (failure_handler, o) def failure_handler(o): o.handle_failure() This doesn't look like a correct or faithful translation of the original. Here are two possibilities. First: class messageHandler: def run(): msg = self.get_next_msg() d = msg.send() def cbSendFailed(result): if not result: self.handle_failure() d.addErrback(cbSendFailed) return d Next: class messageHandler: @inlineCallbacks def run(): msg = self.get_next_msg() if not (yield msg.send()): self.handle_failure() These are both just straight translations from your version so as to be able to handle a Deferred from `msg.send´. Basically, what I find is that a lot of functional encapsulation is now lost by following reactor pattern. handle_failure is messageHandlers code and makes for pretty viewing if called from inside messageHandler itself. But, due to the twisted nature of reactor pattern, the msg Class - who is functionally a lower class to messageHandler invoking messageHandler's code. You don't need to lose anything. I don't know what your motivation was for re-arranging the code when you wrote the Twisted version, but it doesn't appear to have been necessary. Is there a way to solve this in a more beautiful way? Am I missing something here? Hope this helps, Jean-Paul Thank you Jean-Paul. My code is more complex than what I have mentioned. When I mentioned msg.send, the msg object actually gets the data from DB etc to send. And there are many other items being done. I will try to see whether I can change the code to incorporate what you mentioned. I rewrote most of my code after learning just raw deferreds - I had planned to study inlineCallbacks - but then it slipped my mind - now it has come to bit me. :-( Hi, I tried to update the code as per the suggestion, but to no avail. My system uses Python2.4.3 (cannot move to 2.5) - so I tried to rewrite with deferredGenerators - since I thought inlineCallbacks are similar to deferredGenerators. But I cannot seem to rewrite it in a format where the functional encapsulation is not broken. i.e. as I mentioned in the first example - I have to pass SELF to child objects for them to modify it. The code was not exactly as I mentioned. I will try to explain more below: The code before Twisted was incorporated. class MessageHandler: def send_message(): if self.execute(): #Lots of checks going inside this for i in self.msgs: #Sends many messages at the same time if msg.send(): self.success += 1 else self.failure += 1 class Message: def send(): self.update_data() #The data to be sent is updated here return self.protocol.send() #Any protocol - for this example HTTP is used class Protocol: def send(): HTTP get page if page received: parse page and see parameters if parameters: return True return False The code I rewrote after Twisted was incorporated: class MessageHandler: def send_message(): if self.execute(): #Lots of checks going inside this for i in self.msgs: #Sends many messages at the same time msg.send(self): #Has to send myself to the childclass class Message: def send(h): self.h = h #The message handler object self.update_data() #The data to be sent is updated here return self.protocol.send(self) #Again, sending myself to child class
Re: A Twisted Design Decision
On Wed, 28 Jan 2009 02:02:57 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 27, 9:27 pm, koranthala koranth...@gmail.com wrote: On Jan 27, 6:57 pm, Jean-Paul Calderone exar...@divmod.com wrote: [snip] Thank you Jean-Paul. My code is more complex than what I have mentioned. When I mentioned msg.send, the msg object actually gets the data from DB etc to send. And there are many other items being done. I will try to see whether I can change the code to incorporate what you mentioned. I rewrote most of my code after learning just raw deferreds - I had planned to study inlineCallbacks - but then it slipped my mind - now it has come to bit me. :-( Hi, I tried to update the code as per the suggestion, but to no avail. My system uses Python2.4.3 (cannot move to 2.5) - so I tried to rewrite with deferredGenerators - since I thought inlineCallbacks are similar to deferredGenerators. But I cannot seem to rewrite it in a format where the functional encapsulation is not broken. i.e. as I mentioned in the first example - I have to pass SELF to child objects for them to modify it. Why? You don't do this in the original version of your code. Why do it after switching to Twisted (particularly since you seem to want *not* to)? Jean-Paul -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
On Jan 28, 7:10 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Wed, 28 Jan 2009 02:02:57 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 27, 9:27 pm, koranthala koranth...@gmail.com wrote: On Jan 27, 6:57 pm, Jean-Paul Calderone exar...@divmod.com wrote: [snip] Thank you Jean-Paul. My code is more complex than what I have mentioned. When I mentioned msg.send, the msg object actually gets the data from DB etc to send. And there are many other items being done. I will try to see whether I can change the code to incorporate what you mentioned. I rewrote most of my code after learning just raw deferreds - I had planned to study inlineCallbacks - but then it slipped my mind - now it has come to bit me. :-( Hi, I tried to update the code as per the suggestion, but to no avail. My system uses Python2.4.3 (cannot move to 2.5) - so I tried to rewrite with deferredGenerators - since I thought inlineCallbacks are similar to deferredGenerators. But I cannot seem to rewrite it in a format where the functional encapsulation is not broken. i.e. as I mentioned in the first example - I have to pass SELF to child objects for them to modify it. Why? You don't do this in the original version of your code. Why do it after switching to Twisted (particularly since you seem to want *not* to)? Jean-Paul Without that, I am unable to increment success and failure counters which are part of the message handler object. In the original version, if send fails the return value of protocol.send is propogated back to msg.send and to msg handler.send. But in twisted, it is not so. So, I have to pass in SELF through to increment success and failure counter. Is it possible otherwise in twisted? -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
On Wed, 28 Jan 2009 06:30:32 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 28, 7:10 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Wed, 28 Jan 2009 02:02:57 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 27, 9:27 pm, koranthala koranth...@gmail.com wrote: On Jan 27, 6:57 pm, Jean-Paul Calderone exar...@divmod.com wrote: [snip] Thank you Jean-Paul. My code is more complex than what I have mentioned. When I mentioned msg.send, the msg object actually gets the data from DB etc to send. And there are many other items being done. I will try to see whether I can change the code to incorporate what you mentioned. I rewrote most of my code after learning just raw deferreds - I had planned to study inlineCallbacks - but then it slipped my mind - now it has come to bit me. :-( Hi, I tried to update the code as per the suggestion, but to no avail. My system uses Python2.4.3 (cannot move to 2.5) - so I tried to rewrite with deferredGenerators - since I thought inlineCallbacks are similar to deferredGenerators. But I cannot seem to rewrite it in a format where the functional encapsulation is not broken. i.e. as I mentioned in the first example - I have to pass SELF to child objects for them to modify it. Why? You don't do this in the original version of your code. Why do it after switching to Twisted (particularly since you seem to want *not* to)? Jean-Paul Without that, I am unable to increment success and failure counters which are part of the message handler object. In the original version, if send fails the return value of protocol.send is propogated back to msg.send and to msg handler.send. But in twisted, it is not so. So, I have to pass in SELF through to increment success and failure counter. Is it possible otherwise in twisted? Why isn't the return value of protocol.send propagated back to msg.send? It sounds like it should be. Jean-Paul -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
On Jan 28, 8:36 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Wed, 28 Jan 2009 06:30:32 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 28, 7:10 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Wed, 28 Jan 2009 02:02:57 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 27, 9:27 pm, koranthala koranth...@gmail.com wrote: On Jan 27, 6:57 pm, Jean-Paul Calderone exar...@divmod.com wrote: [snip] Thank you Jean-Paul. My code is more complex than what I have mentioned. When I mentioned msg.send, the msg object actually gets the data from DB etc to send. And there are many other items being done. I will try to see whether I can change the code to incorporate what you mentioned. I rewrote most of my code after learning just raw deferreds - I had planned to study inlineCallbacks - but then it slipped my mind - now it has come to bit me. :-( Hi, I tried to update the code as per the suggestion, but to no avail. My system uses Python2.4.3 (cannot move to 2.5) - so I tried to rewrite with deferredGenerators - since I thought inlineCallbacks are similar to deferredGenerators. But I cannot seem to rewrite it in a format where the functional encapsulation is not broken. i.e. as I mentioned in the first example - I have to pass SELF to child objects for them to modify it. Why? You don't do this in the original version of your code. Why do it after switching to Twisted (particularly since you seem to want *not* to)? Jean-Paul Without that, I am unable to increment success and failure counters which are part of the message handler object. In the original version, if send fails the return value of protocol.send is propogated back to msg.send and to msg handler.send. But in twisted, it is not so. So, I have to pass in SELF through to increment success and failure counter. Is it possible otherwise in twisted? 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. This means that msg_handler has to pass in its object to msg.send which inturn has to send either msg_handler or self to protocol.send so that it is stored in the parameter to the callback. When callback is hit, I use this parameter to call methods in each object. This is what I was trying to say in my first mail that - Twisted, being twisted in its behavior is causing quite a lot of confusion in design decisions - because now I have to break functional encapsulation - by asking lower layer objects to handler upper layer objects behaviors. As I said earlier, maybe I am being completely stupid - there might be a very easy and obvious solution. But I cannot seem to get it at all. -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
On Wed, Jan 28, 2009 at 10:05 AM, koranthala koranth...@gmail.com wrote: On Jan 28, 8:36 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Wed, 28 Jan 2009 06:30:32 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 28, 7:10 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Wed, 28 Jan 2009 02:02:57 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 27, 9:27 pm, koranthala koranth...@gmail.com wrote: On Jan 27, 6:57 pm, Jean-Paul Calderone exar...@divmod.com wrote: [snip] Thank you Jean-Paul. My code is more complex than what I have mentioned. When I mentioned msg.send, the msg object actually gets the data from DB etc to send. And there are many other items being done. I will try to see whether I can change the code to incorporate what you mentioned. I rewrote most of my code after learning just raw deferreds - I had planned to study inlineCallbacks - but then it slipped my mind - now it has come to bit me. :-( Hi, I tried to update the code as per the suggestion, but to no avail. My system uses Python2.4.3 (cannot move to 2.5) - so I tried to rewrite with deferredGenerators - since I thought inlineCallbacks are similar to deferredGenerators. But I cannot seem to rewrite it in a format where the functional encapsulation is not broken. i.e. as I mentioned in the first example - I have to pass SELF to child objects for them to modify it. Why? You don't do this in the original version of your code. Why do it after switching to Twisted (particularly since you seem to want *not* to)? Jean-Paul Without that, I am unable to increment success and failure counters which are part of the message handler object. In the original version, if send fails the return value of protocol.send is propogated back to msg.send and to msg handler.send. But in twisted, it is not so. So, I have to pass in SELF through to increment success and failure counter. Is it possible otherwise in twisted? 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. This means that msg_handler has to pass in its object to msg.send which inturn has to send either msg_handler or self to protocol.send so that it is stored in the parameter to the callback. When callback is hit, I use this parameter to call methods in each object. This is what I was trying to say in my first mail that - Twisted, being twisted in its behavior is causing quite a lot of confusion in design decisions - because now I have to break functional encapsulation - by asking lower layer objects to handler upper layer objects behaviors. As I said earlier, maybe I am being completely stupid - there might be a very easy and obvious solution. But I cannot seem to get it at all. I'm sure you're not completely stupid, but there is an easy and obvious solution - you should be returning the *deferred* up the callstack. That will allow the MessageHandler to attach callbacks/errbacks to it, without needing to pass self all the way down the call stack and have a proxy object manage it. -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
On Wed, 28 Jan 2009 08:05:13 -0800 (PST), koranthala koranth...@gmail.com wrote: On Jan 28, 8:36 pm, Jean-Paul Calderone exar...@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 -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
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. Oh! This makes it very clear. Thank you very much Jean-Paul and Chris Mellon. My view of deferred was very different from this. That was the reason behind these persistent questions. My view of deferred was that of it being a mechanism to provide asynchronous behavior and nothing more. The twisted documentation explicitly mentions this - 'Twisted’s Deferred abstraction, which symbolises a ’promised’ result and which can pass an eventual result to handler functions.' But with my earlier view I understood it completely differently. Thank you once more, Jean-Paul Chris for taking your valuable time out to help me out. -- http://mail.python.org/mailman/listinfo/python-list
A Twisted Design Decision
Twisted, being twisted in its behavior is causing quite a lot of confusion in design decisions. I will put forward a comparison of reactor and non-reactor patterns. The code is not exact - whatever is shown is the gist of it. For example, a message handler - in a usual scenario: class messageHandler: def run(): msg = self.get_next_msg() if not msg.send(): self.handle_failure() To handle parallel execution, we will have to use threads, but the code flow is similar. How do we do the same in a reactor pattern (Twisted)? msg.send will cause a deferred to be raised - the failure, if it happens will happen much later. i.e. other than sending messageHandler object in msg.send(), I cannot see any mechanism of running handle_failure. In Twisted: class messageHandler: def run(): msg = self.get_next_msg() msg.send(self): class msgClass: def send(o): d = deferred.addCallBack(success_handler, o).addErrBack (failure_handler, o) def failure_handler(o): o.handle_failure() Basically, what I find is that a lot of functional encapsulation is now lost by following reactor pattern. handle_failure is messageHandlers code and makes for pretty viewing if called from inside messageHandler itself. But, due to the twisted nature of reactor pattern, the msg Class - who is functionally a lower class to messageHandler invoking messageHandler's code. Is there a way to solve this in a more beautiful way? Am I missing something here? -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
On Tue, 27 Jan 2009 05:46:25 -0800 (PST), koranthala koranth...@gmail.com wrote: Twisted, being twisted in its behavior is causing quite a lot of confusion in design decisions. I'm not sure I agree with your premise. ;) I will put forward a comparison of reactor and non-reactor patterns. The code is not exact - whatever is shown is the gist of it. For example, a message handler - in a usual scenario: class messageHandler: def run(): msg = self.get_next_msg() if not msg.send(): self.handle_failure() To handle parallel execution, we will have to use threads, but the code flow is similar. How do we do the same in a reactor pattern (Twisted)? msg.send will cause a deferred to be raised - the failure, if it happens will happen much later. i.e. other than sending messageHandler object in msg.send(), I cannot see any mechanism of running handle_failure. In Twisted: class messageHandler: def run(): msg = self.get_next_msg() msg.send(self): class msgClass: def send(o): d = deferred.addCallBack(success_handler, o).addErrBack (failure_handler, o) def failure_handler(o): o.handle_failure() This doesn't look like a correct or faithful translation of the original. Here are two possibilities. First: class messageHandler: def run(): msg = self.get_next_msg() d = msg.send() def cbSendFailed(result): if not result: self.handle_failure() d.addErrback(cbSendFailed) return d Next: class messageHandler: @inlineCallbacks def run(): msg = self.get_next_msg() if not (yield msg.send()): self.handle_failure() These are both just straight translations from your version so as to be able to handle a Deferred from `msg.send´. Basically, what I find is that a lot of functional encapsulation is now lost by following reactor pattern. handle_failure is messageHandlers code and makes for pretty viewing if called from inside messageHandler itself. But, due to the twisted nature of reactor pattern, the msg Class - who is functionally a lower class to messageHandler invoking messageHandler's code. You don't need to lose anything. I don't know what your motivation was for re-arranging the code when you wrote the Twisted version, but it doesn't appear to have been necessary. Is there a way to solve this in a more beautiful way? Am I missing something here? Hope this helps, Jean-Paul -- http://mail.python.org/mailman/listinfo/python-list
Re: A Twisted Design Decision
On Jan 27, 6:57 pm, Jean-Paul Calderone exar...@divmod.com wrote: On Tue, 27 Jan 2009 05:46:25 -0800 (PST), koranthala koranth...@gmail.com wrote: Twisted, being twisted in its behavior is causing quite a lot of confusion in design decisions. I'm not sure I agree with your premise. ;) I will put forward a comparison of reactor and non-reactor patterns. The code is not exact - whatever is shown is the gist of it. For example, a message handler - in a usual scenario: class messageHandler: def run(): msg = self.get_next_msg() if not msg.send(): self.handle_failure() To handle parallel execution, we will have to use threads, but the code flow is similar. How do we do the same in a reactor pattern (Twisted)? msg.send will cause a deferred to be raised - the failure, if it happens will happen much later. i.e. other than sending messageHandler object in msg.send(), I cannot see any mechanism of running handle_failure. In Twisted: class messageHandler: def run(): msg = self.get_next_msg() msg.send(self): class msgClass: def send(o): d = deferred.addCallBack(success_handler, o).addErrBack (failure_handler, o) def failure_handler(o): o.handle_failure() This doesn't look like a correct or faithful translation of the original. Here are two possibilities. First: class messageHandler: def run(): msg = self.get_next_msg() d = msg.send() def cbSendFailed(result): if not result: self.handle_failure() d.addErrback(cbSendFailed) return d Next: class messageHandler: @inlineCallbacks def run(): msg = self.get_next_msg() if not (yield msg.send()): self.handle_failure() These are both just straight translations from your version so as to be able to handle a Deferred from `msg.send´. Basically, what I find is that a lot of functional encapsulation is now lost by following reactor pattern. handle_failure is messageHandlers code and makes for pretty viewing if called from inside messageHandler itself. But, due to the twisted nature of reactor pattern, the msg Class - who is functionally a lower class to messageHandler invoking messageHandler's code. You don't need to lose anything. I don't know what your motivation was for re-arranging the code when you wrote the Twisted version, but it doesn't appear to have been necessary. Is there a way to solve this in a more beautiful way? Am I missing something here? Hope this helps, Jean-Paul Thank you Jean-Paul. My code is more complex than what I have mentioned. When I mentioned msg.send, the msg object actually gets the data from DB etc to send. And there are many other items being done. I will try to see whether I can change the code to incorporate what you mentioned. I rewrote most of my code after learning just raw deferreds - I had planned to study inlineCallbacks - but then it slipped my mind - now it has come to bit me. :-( -- http://mail.python.org/mailman/listinfo/python-list