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()

运行结果如下:

 

 

posted on 2013-08-01 21:35  |残阳|露  阅读(1249)  评论(0编辑  收藏  举报

导航