专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Python » xmlrpcpython:Python Web 服务开发者: 针对 Python 的 XML-RPC »正文

xmlrpcpython:Python Web 服务开发者: 针对 Python 的 XML-RPC

来源: 发布时间:星期四, 2009年1月8日 浏览:22次 评论:0
  XML-RPC 是种比 SOAP 更早、简单轻量级 Web 服务技术这个月Mike Olson 和 Uche Ogbuji 将讨论 Python 中 XML-RPC 工具

  XML-RPC 是 XML Web 服务鼻祖它是个用于远程过程(remote procedure callRPC)简单规范标准这种使用 HTTP 作为传输协议并使用 XML 词汇表作为消息有效负载由于 XML-RPC 非常简单(整个规范标准打印出来还不到十页纸)它已经变得非常流行现在大多数语言都有了标准或已经可用 XML-RPC 实现这些语言中包括 Python它在版本 2.2 中就开始捆绑 xmlrpclib(Fredrik Lundh 开发 XML-RPC 实现)了Joe Johnston 发表在 IBM developerWorks 上文章“Using XML-RPC for Web services”(请参阅 参考资料)在前 3节讨论了 XML-RPC 基础知识如果您需要回顾下这些基本技术可以从那篇文章开始在本文中我们将重点讨论如何使用 Python 实现要运行本文中举例您必须安装 Python 2.2另外在上篇文章中我们还讨论了 XML-RPC、SOAP 和其他分布式编程技术性能对比在作出部署 XML-RPC 主要决定的前您可能希望先阅读下那篇文章

  客户机

  编写 Python XML-RPC 客户机非常容易模块 xmlrpclib 拥有所需全部工具个远程 XML-RPC 对象您可以创建个代理对象它用 XML-RPC 把请求转发给服务器代理对象外观和感觉就和常规 Python 对象并且请求就是简单 清单 1(currtime.py)使用 XML-RPC 从 UserLand 服务器获取当前时间(请参阅 参考资料以了解更多有关这个服务信息)

  清单 1(currtime.py):使用 XML-RPC 获取当前时间

 import xmlrpclib
#Port 80 is the default
server = xmlrpclib.ServerProxy("http://time.xmlrpc.com")
currentTimeObj = server.currentTime
currtime = currentTimeObj.getCurrentTime
pr currtime
pr currtime.value


  实际上被代理是服务器这个服务器是通过化 ServerProxy 类个例子建立起来我们传入远程服务器完整 URL(您必须在其中包含 URL 模式“http://”)端口还是通常缺省值 80如果远程服务器不在端口 80 上侦听而是在端口 8080 上侦听我们将使用“http://time.xmlrpc.com:8080”服务器代理把它们托管所有实际远程对象都当作常规属性这样我们就可以得到名为 currentTime 远程对象句柄现在我们只需这个代理对象上思路方法即可它会返回当前时间响应是种特殊 XML-RPC 类型名为 DateTime要获得这个对象串表示我们可以使用它 value 属性

  必须澄清点:区分服务器内代理对象这种想法实际上是种幻想XML-RPC 允许思路方法名内包含点号而且大家般都习惯使用诸如 pseudo_object.foo 这样思路方法名这个思路方法名允许客户机把它当作是对名为 pseudo_object 远程对象 foo 思路方法然而对于 XML-RPC 协议而言pseudo_object.foo 只是在远程服务器上定义个名为 pseudo_object.foo 思路方法稍后您会明白为什么这个区别很重要

  运行该脚本结果是:

$ python currtime.py
<DateTime 20020808T10:43:06 at 81dd0ec>
20020808T10:43:06


  特殊类型

  我们已经看到根据规范标准定义 DataType 是 Python XML-RPC 实现中使用种特殊类型如果 XML-RPC 系统要求这种类型就必须使用它来进行 XML-RPC 系统输入和输出换句话说如果个远程接收 DateTime 参数您就不能向它发送象“20020808T10:43:06”这样您将首先构建个 DateTime 类例子例如:

datetime_arg = xmlrpclib.DateTime("20020808T10:43:06")
remote_obj.method(datetime_arg)


  还有其他几种这样特殊类型 Boolean 和 Binary 是基本数据类型特殊 Fault 对象则用于异常处理自从 Python 2.3 引入了本机(native)布尔类型 bool 后 Boolean 可能就会逐渐被弃用了 Binary 和串区别它不限制可以传输什么样字节其他 XML-RPC 类型用本机 Python 对象表示其中列表和元组用来代替字典用来代替结构需要特别注意编码XML-RPC 有个倍受批评限制就是它只支持 ASCII 串(或 2进制缓冲块)传输它根本不提供任何编码支持 清单 2尝试使用 Useful Inc 样本串回送(echo)服务(该服务只是接收串并返回个同样串)

  清单 2(echo.py):简单串回送客户机

 import xmlrpclib
server = xmlrpclib.ServerProxy("http://xmlrpc.usefulinc.com/demo/server.php")
eg_obj = server.examples
result = eg_obj.echo(u"Freude, sch&ouml;nerg&ouml;tterfunken")
pr result


  但如果您运行它就会感受到用户经常抱怨 Python 中编码苦恼了:

$ python echo.py
Traceback (most recent call last):
 File "echo.py", line 8, in ?
  pr result
UnicodeError: ASCII encoding error: ordinal not in range(128)


  第个解决方案是编码为 UTF-8这个方案看上去不错但遗憾由于 7 位 ASCII 范围“容纳”不了 UTF-8这个解决方案行不通我们可以使用解决方案是使用 UTF-7ASCII 范围可以容纳它但这种编码却不常用并且更冗长要使用 UTF-7请用下面代码代替相应代码行:

result = eg_obj.echo(u"Freude,sch&ouml;nerg&ouml;tterfunken".encode("utf-7"))

  结果是:

$ python echo.py
Freude, sch+APY-ne g+APY-tterfunken


  很遗憾这个方案也行不通它会篡改被远程发送并要求允许各方的间进行带外传输而这种情况下串是 UTF-7 编码如果可以在各方的间建立这种通信那么服务器就还可以接受 2进制对象而不是这意味着可以使用 UTF-8但这只是在逃避协议本身个明显问题或许这也是考虑使用 SOAP 个很好理由 SOAP 已经完全国际化了

  处理

  当服务器需要发出信号时它使用 XML-RPC fault 对象来执行在 Python 中这是通过使用个特殊异常对象来解释该对象会给出码和段描述性 清单 3(getstate.py)使用个 XML-RPC 服务来根据传进来数字返回状态名称该数字代表按字母排序状态索引我们故意使用个假值 -1这个值会导致服务器发生:

  清单 3(getstate.py):故意引发 XML-RPC 客户机

 import xmlrpclib
server = xmlrpclib.ServerProxy("http://xmlrpc.usefulinc.com/demo/server.php")
eg_obj = server.examples
try:
  result = eg_obj.getStateName(-1)
except xmlrpclib.Fault, fault:
  pr fault.faultCode
  pr fault.faultString


  运行结果是:

$ python getstate.py
800
I don't have a state for the index '-1'


  如果是 XML-RPC 工具而不是服务本身遇到了问题(例如您给它提供了个无法到达 URL)那么将产生个 ProtocolError 异常对象而不是 Fault 对象

  XML-RPC 服务器

  Python 还附带 SimpleXMLRPCServer 它是个用来实现 XML-RPC 服务器模块要公开 XML-RPC 服务您可以向 SimpleXMLRPCServer 模块中和其同名个例子注册或例子最直接思路方法就是编写带有实现您需求思路方法例子然后注册这个例子但在这种情况下思路方法名不能包含点号因此我们也就不能再使用前面讨论过手段让服务器看起来代表多个对象这样影响不久将变得非常清楚但首先让我们来创建个日历服务器比如我们直用来演示 SOAP 服务器那种 清单 4(calserver.py)是 XML-RPC 日历服务器实现:

  清单 4:XML-RPC 日历服务器

 import calendar, SimpleXMLRPCServer
#The server object
Calendar:
  def getMonth(self, year, month):
     calendar.month(year, month)
  def getYear(self, year):
     calendar.calendar(year)
calendar_object = Calendar
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8888))
server.register_instance(calendar_object)
#Go o the listener loop
pr "Listening _disibledevent= server.getMonth(2002, 8)
pr month


  在这里您可以看到我们不在思路方法名中包含点号影响我们不是首先从服务器获得个伪对象(它实际上只表示从思路方法名点号前提取部分)而是只需服务器代理本身思路方法输出结果是:

$ python calclient.py
   August 2002
Mo Tu We Th Fr Sa Su
     1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31


  结束语

  XML-RPC 比 SOAP 更简单在开放源代码项目中非常流行它是任何语言或框架目前都必须提供基本工具箱所以在 Python 中添加新 XML-RPC 模块是很受欢迎但它也有自己缺点主要就是对编码支持不够编码支持对英语有种令人吃惊偏向在国际化重要性已被充分理解今天看来这是很不合时宜

  在下部分我们将研究针对另个已经广泛流行 Web 服务接口 Python 工具这个接口就是 RDF 站点摘要(RDF site summaryRSS)



0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: