RE: [Twisted-Python] RE: waiting on transport return
I'm not trying to bump my question, but if someone could tell me if I'm just being stupid and missing something with this code or that it isn't possible to do what I need with a spawned process? If I know it isn't possible, I can just continue down the path I am. It's not too much of a pain, but it just feels...wrong. Thanks, Jon -----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python-bounces@twistedmatrix.com] On Behalf Of jmbenski Sent: Tuesday, December 06, 2005 7:58 PM To: twisted-python@twistedmatrix.com Subject: [Twisted-Python] RE: waiting on transport return Ok, I need some help to write some code using deferred's the way they were meant, not the way I've bastardized them. My framework... I have a client that will connect to a server and MAINTAIN that connection. I can't create a protocol factory. The server and the client communicate commands through stdin and stdout. I need to write my commands to the server and wait for the response in some cases. I've setup a system that passes a deferred chain to my process protocol and once my process knows that the data it needs is received it will kick off the deferred chain that happens after that response. This seems backwards. From my reading and understanding of deferreds, they should bubble down and not have to be pushed up. How do I handle the case of some protocol command kicking off the rest of a deferred chain or of passing back a deferred, so that I can add to it the things that need to run? class SyncManagerProtocol(protocol.ProcessProtocol): def __init__(self ): self.dataStore = "" ##queue that holds the commands self.cmdQueue = list() ##queue that holds the callback function to call once the call returns self.deferredQueue = list() def outReceived(self, data): if len(self.cmdQueue) > 0: ##take the data and shove it into our internal store self.dataStore += data ##determine what is good data cmd = self.cmdQueue[0] ##look for the command the is next in the queue. grab all the return data ##between the command block. ## syncCmd { ## return data goes here ## } syncCmd cmdBlock = r"%s {(?P<cmd>.*)} %s(?P<rest>.*)" % (cmd, cmd) errBlock = r"invalid {(?P<errMsg>.*)}" cmdMatch = re.compile( cmdBlock, re.S ).search( self.dataStore ) if cmdMatch: ##set the rest of the data to the dataStore. This clears out the current contents ##but keeps any extra data that may be coming in from the next command self.dataStore = cmdMatch.group( "rest" ) ##clean up this command self.commandComplete( cmdMatch.group("cmd").lstrip() ) ##This is called if all the data we need has been returned. def commandComplete(self, cmdData): ##pop this command since we are done with it self.cmdQueue.pop(0) ##pop the deferred that matches this command deferred = self.deferredQueue.pop(0) ##pass the results to the deferred deferred.callback( cmdData ) ##interface to the process that sends a command to execute def sendCommand( self, cmd, args, deferred ): ##store the command in the queue, so we can check it when we get data self.cmdQueue.append( cmd ) ##store the deferred in the queue that we need to run when this command has been completed self.deferredQueue.append( deferred ) ##write out command to the process cmd = cmd + " " + args + "\n" self.transport.write( cmd ) ## This code is my client interface class to the server that holds the processProtocol instance. ## #setup a command that will handle errors or good data d = defer.Deferred().addCallback( self.handleThisCommand ) #run the calling function handler that will handle an error or returned data. This will allow something like a GUI to process data that will now be available d.addCallback( self.theRestOfTheCommands ) cmd = "some command goes here" self.processProtocol.sendCommand( "syncCmd", cmd, d)
On Fri, 9 Dec 2005 09:03:52 -0700, jmbenski@micron.com wrote:
I'm not trying to bump my question, but if someone could tell me if I'm just being stupid and missing something with this code or that it isn't possible to do what I need with a spawned process? If I know it isn't possible, I can just continue down the path I am. It's not too much of a pain, but it just feels...wrong.
The code mostly seems good to me. The only thing I might change is completely trivial: instead of passing a Deferred in to sendCommand, I'd have sendCommand be responsible for creating the Deferred and then return it, so your application code would look like this - d = self.processprotocol.sendCommand("syncCmd", cmd) d.addCallback(self.handleTheCommand) d.addCallback(Self.theRestOfTheCommands) I'm not sure from where your unhappyness with the version you posted stems, so I'm not sure what other comments to make. Jean-Paul
participants (2)
-
Jean-Paul Calderone
-
jmbenski@micron.com