Python的XMLRPC机制:实现跨进程间、client/server端通信
SimpleXMLRPCServer模块式python语言的一个基于 xml 格式的进程间通信的基础框架。
SimpleXMLRPCServer是一个单线程的服务器,这意味着,如果几个客户端同时发出多个请求,其它的请求就必须等待第一个请求完成以后才 能继续。此处也有一个解决方法。
例子代码如下:
创建一个server端主进程,并且利用一个线程开启一个server线程,并开启一个client进程作为child 进程。
MyRemoteService包含三个serveice服务方法,我们测试Add方法,从server端返回计算结果。
#-*- coding: UTF-8 -*- import wx import threading import sys from SimpleXMLRPCServer import SimpleXMLRPCServer class XMLRPCServerThread(threading.Thread): def __init__(self, remoteServiceInstance, host='127.0.0.1', port=1234): self._RemoteServiceInstance = remoteServiceInstance self._Host = host self._Port = port threading.Thread.__init__(self) def stop(self): self._Server.shutdown() def run(self): self._Server = SimpleXMLRPCServer( (self._Host, self._Port), logRequests=False, allow_none = True ) self._Server.register_instance( self._RemoteServiceInstance ) self._Server.serve_forever() class MyRemoteService(object): def __init__(self, obj): self.obj = obj def Add(self, a, b): return a + b def NoReturn(self): print 'xxxx' def Empty(self): return u'中国 .' class MyFrame(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, -1, "Server service") mainPanel = wx.Panel(self, size = (300, 400)) mainPanel.SetBackgroundColour(wx.Colour(0,122,200)) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(mainPanel, 1, wx.EXPAND) self.SetSizerAndFit(sizer) ## @detail ShellApp主应用程序的核 class ShellApp(wx.App): def OnInit(self): mainFrame = MyFrame(None) self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded) self.__ServerThread = self.__GetRPCThread() self.__ChildProcess = wx.Process(self) pid = wx.Execute('python remoteClient.py', wx.EXEC_NOHIDE|wx.EXEC_ASYNC, self.__ChildProcess) mainFrame.Show(True) return True def __GetRPCThread(self, host='localhost', port=1234): remoteObj = MyRemoteService(self) rpcThread = XMLRPCServerThread(remoteObj, host, port) rpcThread.start() return rpcThread def OnProcessEnded(self, evt): print 'Child process exist' self.__ChildProcess.Destroy() self.__ServerThread.stop() self.Exit() # @detail main程序的主入口程序 if __name__ == '__main__': app = ShellApp() #重新定向wxpython的输出输入和错误输出到系统标准输入输出 sys.stdin = sys.__stdin__ sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ app.MainLoop()
client端代码如下:
#-*- coding: UTF-8 -*- import wx import sys import xmlrpclib #客户端 from SimpleXMLRPCServer import SimpleXMLRPCServer class MyFrame(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, -1, "Client app") mainPanel = wx.Panel(self, size = (300, 200)) addButton = wx.Button(mainPanel, -1, 'Add') addButton.Bind(wx.EVT_BUTTON, self.__OnAddClicked) self._AText = wx.TextCtrl(mainPanel, -1, '10') self._AddText = wx.StaticText(mainPanel, -1, ' + ') self._BText = wx.TextCtrl(mainPanel, -1, '23') self._Label = wx.StaticText(self, -1, ' = ') self._SumText = wx.TextCtrl(mainPanel) panelSizer = wx.BoxSizer(wx.HORIZONTAL) panelSizer.Add(addButton, 0, wx.ALL, 6) panelSizer.Add(self._AText, 0, wx.ALL, 6) panelSizer.Add(self._AddText, 0, wx.ALL, 6) panelSizer.Add(self._BText, 0, wx.ALL, 6) panelSizer.Add(self._Label, 0, wx.ALL, 6) panelSizer.Add(self._SumText, 0, wx.ALL, 6) mainPanel.SetSizer(panelSizer) mainPanel.SetBackgroundColour(wx.Colour(122,12,20)) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(mainPanel, 1, wx.EXPAND) self.SetSizerAndFit(sizer) self._Proxy = xmlrpclib.ServerProxy('http://127.0.0.1:1234') def __OnAddClicked(self, evt): a = int(self._AText.GetLabel()) b = int(self._BText.GetLabel()) sum = self._Proxy.Add(a, b) self._SumText.SetLabel('%s'%sum) self._Proxy.NoReturn() ## @detail ShellApp主应用程序的核 class ShellApp(wx.App): def OnInit(self): mainFrame = MyFrame(None) mainFrame.Show(True) return True # @detail main程序的主入口程序 if __name__ == '__main__': app = ShellApp() #重新定向wxpython的输出输入和错误输出到系统标准输入输出 sys.stdin = sys.__stdin__ sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ app.MainLoop()
运行结果如下: