Python的XMLRPC简介及小技巧
时间:2009-09-02 01:07 来源:可爱的python 作者:秩名 点击:258次
我觉得,SimpleXMLRPCServer模块可以说是Python的招牌菜。 编写客户端提交数据到服务器处理是程序员最常碰到的几个问题之一。各种不同的语言对此都有相应的解决方案。比如Unix下,C程序
我觉得,SimpleXMLRPCServer模块可以说是Python的招牌菜。
编写客户端提交数据到服务器处理是程序员最常碰到的几个问题之一。各种不同的语言对此都有相应的解决方案。比如Unix下,C程序员们可以用SUNRPC,Java程序员则使用RMI来处理。大多数语言还都可以使用Web Service或者ICE。它们的使用方法类似,编写一个接口定义文件,用一个工具处理并生成代码,加入到工程中,最后编译生成目标文件运行。有用过这类工具的朋友们,脑子里应该都会闪出一个字——烦!真的是谁用谁知道。
Python同样也提供了一个基于XMLRPC的解决方案,不过用法很简单:
首先,就好像在编写普通的程序那样子编写服务器。
接着使用SimpleXMLRPCServer模块运行XMLRPC服务器,在其中注册服务器提供的函数或者对象。
最后,在客户端内使用xmlrpclib.ServerProxy连接到服务器,想要调用服务器的函数,直接调用ServerProxy即可。
一个最简单的hello,word示例:
#helloserver.py from SimpleXMLRPCServer import SimpleXMLRPCServer def hello(): print "hello,world!" svr=SimpleXMLRPCServer(("", 8080), allow_none=True) svr.register_function(hello) svr.serve_forever() #helloclient.py from xmlrpclib import ServerProxy svr=ServerProxy("http://localhost:8080") svr.hello() 先后运行helloserver.py和helloclient.py就可以看到控制台输出hello,world
不过,美中不足的是,SimpleXMLRPCServer是一个单线程的服务器。这意味着,如果几个客户端同时发出多个请求,其它的请求就必须等待第一个请求完成以后才能继续。这里有个技巧解决这个问题:
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SocketServer import ThreadingMixIn
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):pass
现在把helloserver改一改:
svr=ThreadXMLRPCServer(("", 8080), allow_none=True)
现在服务器就支持多线程并发了。
XMLRPC一个标准协议,定义了如何使用HTTP和XML来传递多种类型数据。据我观察,xmlrpclib对于日期/时间类型的有特殊的支持。假如有一个服务器提供的函数是:
def toluar(d):pass
这原本是一个将阳历转换成阴历的函数。要求d是datetime模块里的datetime类型。虽然客户端确实传入的确实是datetime类型,服务器却会将其解释为xmlrpclib.DateTime类型。 解决办法是:
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer): #从SimpleXMLRPCServer模块抄出来的代码 def _marshaled_dispatch(self, data, dispatch_method = None): try: params, method = xmlrpclib.loads(data, use_datetime=True) #这里加了一个use_datetime # generate response if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params) # wrap response in a singleton tuple response = (response,) response = xmlrpclib.dumps(response, methodresponse=1, allow_none=self.allow_none, encoding=self.encoding) except Fault, fault: response = xmlrpclib.dumps(fault, allow_none=self.allow_none, encoding=self.encoding) except: # report exception back to server exc_type, exc_value, exc_tb = sys.exc_info() response = xmlrpclib.dumps(xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),encoding=self.encoding, allow_none=self.allow_none,) return response svr=ThreadXMLRPCServer(("", 8080), allow_none=True) 客户端方面则比较简单:
svr=ServerProxy("http://localhost:8080/", allow_none=True, use_datetime=True) 注意 use_datetime参数默认是False