类型:Python,创建时间:Jan. 1, 2012, 2:30 p.m.
标题无“转载”即原创文章,版权所有。转载请注明来源:http://hgoldfish.com/blogs/article/50/。
我觉得,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.py
改一改:
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: #唯一的改动是这里加了一个use_datetime params, method = xmlrpclib.loads(data, use_datetime=True) # 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
标题无“转载”即原创文章,版权所有。转载请注明来源:http://hgoldfish.com/blogs/article/50/。
A1233(Jan. 2, 2012, 8:22 a.m.)
您好,我在您的blog上拜读了您的文章,在我的实际项目中正好用到,其中发现了让自己疑惑的问题,能帮我指点一下吗?QQ:346264877 请指教
panda(March 23, 2012, 8:32 p.m.)
ThreadingMixIn
要注意MixIn
的I
是大写的。