[Twisted-Python] PB and multiple apps

Jeff Grimmett grimmtooth at softhome.net
Thu Feb 13 19:20:30 EST 2003


> It's not at all clear to me what you're doing.  Can you post 
> some code?

I'll try to explain in more detail since the source is a mess right now
with all the commented code etc. With snippets.

App 1: it's a debugging window that I can run or not as needed. When it
is up it receives messages from the other app and feeds them to my
wxApp.

 import sys

 from myLib import *
 from twisted.internet import app
 from twisted.internet import wxsupport
 from twisted.spread import pb

# wx app stuff trimmed for brevity.

# The handler for incoming remote calls.
# I pass it a reference to my wxApp's top frame.
class DBHandler(pb.Root):
  def __init__	(self, win):
    self.Commands = {'Msg'  : self.doMsg,
                     'Ping' : self.doPing
                    }

    self.win = win

    # This is the function registered with Debug.Debug() (below)
    def remote_DoCommand(self, msg):
      if msg['Command'] in self.Commands:
        return(apply(self.Commands[msg['Command']], [msg]))
      else:
        return(-1)

    # Log a message
    def doMsg(self, msg):
      self.win.LogIt(msg['Msg'])
      return(0)

    # Return a ping. 
    def doPing(self, msg):
      return(1)

# Here's where I set up the app and run it
def RunServer(args):
  # Set up the wxApp
  myWXApp = MyApp(0)

  # Replace the wx event loop with the twisted
  # event loop and adds wx event handling.
  wxsupport.install(myWXApp)

  # Our PB factory
  ctl = pb.BrokerFactory(DBHandler(myWXApp.frame))
  # And set up the app
  myApp = app.Application("Debug")

  myApp.listenTCP(Debug.DBPort, ctl)
  myApp.run(save=0)

  sys.exit(0)

if __name__ == "__main__":
  RunServer(sys.argv)

## Following is the library code that is used by the other app
## to send debugging info to the debugger.

 From twisted.internet import reactor
 from twisted.spread import pb

 import time
 
DBPort = 7747

Me = Entities['Debugger'] # def for Entities not included for brevity

# This is a very lame bucket to hold data in a dynamic way
# so that the data can be passed back and forth between functions.
# Needs to be replaced with something a bit slicker.
 
class Bucket:
 def __init__(self, msg):
   self.SetMsg(msg)
   self.SetRC(-1)
  def SetMsg(self, msg):
   self.msg = msg
  def GetMsg(self):
    return(self.msg)
  def SetRC(self, rc):
    self.rc = rc
  def GetRC(self):
    return(self.rc)

bucky = Bucket('')

# Following three functions are PB functions. Based on twisted example
# code.

def gotObject(object):
  object.callRemote ( "DoCommand", {'Command': 'Msg',
'Msg':bucky.GetMsg()}).addCallback(gotCommand)
	  
def gotCommand(rc):
  bucky.SetRC(rc)
  reactor.stop()
	  
# This fires if we don't manage to connect.
def gotNoObject(reason):
  bucky.SetRC(-1)
  reactor.stop()

# Sets up the debugging session and returns response
def Debug(ID, msg):
  if ID == 0:
    return(-1)

  txt = '%s :: [%s] %s' %	( time.strftime('%Y.%m.%d %H:%M:%S'), 
                             ID, msg
                           ) 

  bucky.SetMsg(txt)
  pb.getObjectAt("localhost", DBPort, 30).addCallbacks(gotObject,
gotNoObject)
  reactor.run()
  return(bucky.GetRC())


The other app is very similar to the above, with a similar library that
passes slightly different data around.  The key difference is that the
other app has calls to Debug.Debug() within the handler itself.  Here is
the handler:

class CtlHandler(pb.Root):
  def __init__ (self):
    self.Commands = { 'Shutdown' : self.doShutdown
                    }

  def remote_DoCommand(self, msg):
    print msg

    # THIS IS WHERE IT DIES
    Debug.Debug (Me, "Received Control message [%s] from [%s]" % (
msg['Command'],  msg['From'] ) )
    # If I remove the above, all works well. If I don't, this app
    # closes.


    if	msg['Command'] in self.Commands:
      return(apply(self.Commands[msg['Command']], [msg]))
    else:
      Debug.Debug(Me, "**** Unknown Control message [%s]!" %
msg['Command'])
      return({'Status':'Unknown Command', 'RC':-1})

  def doShutdown(self, msg):
    Debug.Debug(Me, "***** CONTROL SHUTTING DOWN IN 3 SECONDS")
    reactor.callLater(20, self.endShutdown)
    return({'Status':'OK', 'RC':0})

  def endShutdown(self):
    sys.exit(0)


The factory, setup, and library code is nothing unusual but I can post
it if you need to see it.





More information about the Twisted-Python mailing list