How to get the status of spawn process in twisted python?
Question: I want to trigger many long running processes continiously. And, based on the
status returned of each process executed, I need to perform other tasks. In
the below example, I'm able to spawn processes, but I'm not able to
capture/get the details of the spawn processes execution status returned to
mail loop(i.e in CmdProtocol class).

I'm new to this twisted python concepts - Can someone help me here?

    
    
    import sys
    from twisted.internet.protocol import ServerFactory, ProcessProtocol
    from twisted.protocols.basic import LineReceiver
    from twisted.internet import reactor
    from twisted.internet import protocol
    import os
    import signal
    
    
    class MyPP(protocol.ProcessProtocol):
        def __init__(self):
            self.parent_id = os.getpid()
    
        def connectionMade(self):
            print "connectionMade!"
            print "Parent id = %s" % self.parent_id
            print "Child process id = %s" % self.transport.pid
    
        def outReceived(self, data):
            print "out", data
    
        def errReceived(self, data):
            print "error", data
    
        def inConnectionLost(self):
            print "inConnectionLost! stdin is closed! (we probably did it)"
            print "Parent id = %s" % self.parent_id
            print "Child process id closes STDIN= %s" % self.transport.pid    
    
        def outConnectionLost(self):
            print "outConnectionLost! The child closed their stdout!"
            print "Parent id = %s" % self.parent_id
            print "Child process id closes STDOUT = %s" % self.transport.pid                
    
        def errConnectionLost(self):
            print "errConnectionLost! The child closed their stderr."
            print "Parent id = %s" % self.parent_id
            print "Child process id closes ERRCONN = %s" % self.transport.pid    
    
        def processExited(self, reason):
            print "processExited %s, status %d" % (self.transport.pid, reason.value.exitCode,)
    
        def processEnded(self, reason):
            print "%s processEnded, status %d" % (self.transport.pid, reason.value.exitCode,)
            print "quitting"
    
    class CmdProtocol(LineReceiver):
    
        delimiter = '\n'
        def connectionMade(self):
            self.client_ip = self.transport.getPeer()
            print "Client connection from %s" % self.client_ip
    
        def processcmd(self):
            pp = MyPP()
            cmd = ['c:\Python27\python.exe', '-u',  'print_hi.py']
            print "Calling processcmd - <%s>" % cmd
            reactor.spawnProcess(pp, cmd[0], cmd[1:])
    
        def connectionLost(self, reason):
            print "Lost client connection.  Reason: %s" % reason
    
        def lineReceived(self, line):
            if not line: return
            # Parse the command
            print 'Cmd received from %s : %s' % (self.client_ip, line)
            commandParts = line.split()
    
            if len(commandParts) > 0:
                command = commandParts[0].lower()
                args = commandParts[1:]
                try:
                    print "Command received : <%s>" % command
                    method = getattr(self, command)
                except AttributeError, e:
                    self.sendLine('Error: no such command.')
                else:
                    try:
                        res = method()
                        print "Returned status:%s" % res
                        self.sendLine('Command executed successfully.')                
                    except Exception, e:
                        self.sendLine('Error: ' + str(e))     
    
        def do_kill(self, pid):
            """kill: Kill a process (PID)"""
            print 'Killing pid:%s' % pid
            res = os.kill(int(pid), signal.SIGTERM)
            print "Kill Status %s" % res
    
    class MyFactory(ServerFactory):
        protocol = CmdProtocol
        def __init__(self):
            print "Factory called"
    
    reactor.listenTCP(8000, MyFactory())
    reactor.run()
    


Answer: This is actually a very basic Python data structures question. You just need
to refer to an instance of `CmdProtocol` from an instance of `MyPP`. Since
`CmdProtocol` is what constructs `MyPP` in the first place, this is easy. Just
change the construction of `MyPP` to look like this:

    
    
    def processcmd(self):
        pp = MyPP(self)
    

and then `MyPP.__init__` to look like this:

    
    
    def __init__(self, cmd_protocol):
        self.parent_id = os.getpid()
        self.cmd_protocol = cmd_protocol
    

Then, in any method on `MyPP`, you can access the relevant `CmdProtocol`
instance with `self.cmd_protocol`.

