The Python web services developer: XML-RPC for Python
摘要:概括地说,您可以将 XML-RPC 认为是简化的 SOAP。它是允许运行在不同操作系统、不同环境中的软件进行基于Internet 过程调用的规范和一组实现。这种远程过程调用使用 HTTP 作为传输协议,XML 作为编码格式。XML-RPC 的定义尽可能简单,但能够传送、处理和返回复杂的数据结构。
The Python web services developer: XML-RPC for Python
Mike Olson, Principal Consultant, Fourthought, Inc.
Summary: XML-RPC is a simple, lightweight web services technology that predates SOAP. In this installment of the Python web services developer, Mike Olson and Uche Ogbuji examine the XML-RPC facilities in Python.
XML-RPC is the granddaddy of XML web services. It is a simple specification for remote procedure calls (RPC) that uses HTTP as the transport protocol and an XML vocabulary as the message payload. It has become very popular because of its simplicity (the
full specification is less than ten printed pages), and most languages now have standard or readily available XML-RPC implementations. This includes Python, which started bundling xmlrpclib, an XML-RPC implementation by Fredrik Lundh, in version 2.2. Joe Johnston's
IBM developerWorks article "Using XML-RPC for web services" (see Resources) covers the basics of XML-RPC in the first three sections. Start there if you need to review the basic technology. In this article, we will focus on using the Python implementation. You must have Python 2.2. to run the examples in this article.
Also, in the last article, we looked at the relative performance of XML-RPC, SOAP, and other distributed programming technologies. You may want to read that before making major decisions to deploy XML-RPC.
Writing a Python XML-RPC client is very easy. The module xmlrpclib has all the needed machinery. In order to invoke a remote XML-RPC object, you create a proxy object which forwards requests to the server using XML-RPC. The proxy object looks and feels just
like a regular Python object, and your requests are simple function calls. Listing 1 (currtime.py) uses XML-RPC to get the current time from the UserLand server (seeResources for more information about this service).
import xmlrpclib #Port 80 is the default |
What is actually being proxied is the server, which is set up by initializing an instance of theServerProxy class. We pass in the full URL of the remote server (you must include the URL scheme "http://"). Port 80 is the default, as usual. If
the remote server were instead listening on port 8080, we would use "http://time.xmlrpc.com:8080". The server proxy has all the actual remote objects they host as regular attributes, and in this way we get a handle to the remote object namedcurrentTime.
Now we can simply call the method on this proxy object, which returns the current time. The response is of a special XML-RPC type called a DateTime. To get a plain string representation of this object, we use itsvalue attribute.
One important clarification: the idea of distinct proxy objects within the server is really an illusion. XML-RPC allows method names to have periods in them, and it is a common convention to use method names such aspseudo_object.foo, that allows
clients to treat it as a call to a methodfoo on a remote object namedpseudo_object. However, as far as XML-RPC protocol is concerned, this is just a method namedpseudo_object.foo defined on the remote server. You'll see later
on why this distinction is important.
The result of running the script:
$ python currtime.py |
DataType, as we've seen, is one special type used in Python's XML-RPC implementation based on the specification. It must be used for input and output to XML-RPC systems if they require such types. In other words, if a remote function takes a DateTime
argument, you cannot send it a string such as "20020808T10:43:06". You would first construct an instance of the DateTime class. For instance:
datetime_arg = xmlrpclib.DateTime("20020808T10:43:06")
|
There are a few other such special types. Boolean and Binary are basic data types, and the specialFault object is used for exception handling.Boolean might be going away since Python 2.3 introduces a native
boolean typebool.Binary is distinct from strings in that it does not restrict what bytes can be transmitted. The other XML-RPC types are represented by native Python objects, with lists and tuples standing in for arrays and dictionaries
for structures. One important warning is about character encodings. A much-criticized limitation of XML-RPC is that it only supports the transmission of ASCII strings (or binary buffers). It offers no character encoding support at all.Listing
2 tries to use Useful Inc's sample string echo service (which simply takes a string and returns the same string).
import xmlrpclib
server = xmlrpclib.ServerProxy("http://xmlrpc.usefulinc.com/demo/server.php")
eg_obj = server.examples
|
However, if you run it, you will find that the string has been corruptedby the remote server:
$ python stringecho.py |
This is because although Python supports Unicode strings, the remotesystem does not. XML-RPC oficially only specifies ASCII as a stringencoding, a well-known and unfortunate limitation.
The first attractive solution to encode to UTF-8, unfortunately, will not work since UTF-8 does not "fit" into the 7-bit ASCII range. One could use is to use UTF-7, which does fit into ASCII range, but this is a less common and more verbose encoding. To
use UTF-7, replace the relevant line with:
result = eg_obj.stringecho(u"Freude,schönergötterfunken".encode("utf-7"))
|
resulting in:
$ python stringecho.py |
This is unfortunate because it distorts the value being sent remotely, and requires an out-of-band understanding between the parties that strings being passed are in UTF-7 encoding. If this sort of communication can be established between the parties, the
server could also accept binary objects rather than strings, which means that UTF-8 could be used. But this is just hacking around a glaring fault in the protocol itself, and perhaps a good reason to consider SOAP, which is properly internationalized.
When the server needs to signal an error, it does so using an XML-RPC fault. This is interpreted in Python using a special exception object which gives a fault code and descriptive string.Listing
3 (getstate.py) uses an XML-RPC service for returning a state name according to a number passed in which represents the index of the state in alphabetic order. We purposefully use a bogus value of-1 which causes the server to raise a fault:
import xmlrpclib
server = xmlrpclib.ServerProxy("http://xmlrpc.usefulinc.com/demo/server.php")
eg_obj = server.examples
|
Which results in:
$ python getstate.py |
If it is the XML-RPC machinery rather than the service itself that encounters a problem (for instance, you give it a URL that cannot be reached), aProtocolError exception object is raised rather than aFault object.
Python also comes with SimpleXMLRPCServer, a module for implementing XML-RPC servers. You can register functions or instances with an instance of theSimpleXMLRPCServer class in the module of the same name, in order to expose XML-RPC
services. The most straightforward way is to just write an instance with methods that do what you need, and then register this instance. However, in this case, method names cannot have periods, and so the trickery we discussed above to make things appear as
if there are multiple objects represented by the server is unavailable. The effect of this will become clear soon, but first of all, let us create a calendar server such as the one we've been using to demonstrate SOAP servers.Listing
4 (calserver.py) is the XML-RPC calendar server implementation:
import calendar, SimpleXMLRPCServer #The server object |
The class Calendar implements the methods we wish to expose. They take numbers and return strings. We create an instance of this object and then an instance of the XML-RPC server class, with which we register the calendar instance. This now
makes the methods getMonth and getYear available on the server. Remember that Python is dynamically typed, and that you will want to add type-checking code to the methods in most cases. Of course Python's rich expressiveness makes
this a breeze, and also means that you can easily do more sophisticated type checking than most languages allow. In the main code, we create a server object, giving it a tuple representing the listening address and port. The address can be a host name or IP
address. Finally, we put this server into its main loop, which is only broken when an operating system signal interrupts it, such as when the user presses CTRL-C. Open up a separate console and run the server script.
To test the server, we write a simple client in Listing 5 (calclient.py):
import xmlrpclib
server = xmlrpclib.ServerProxy("http://localhost:8888")
month = server.getMonth(2002, 8)
|
And here you can see the effect of our not having a period in the method names. Rather than first of all obtaining a pseudo-object from the server (which really just represents an abstraction of the part of the method name before the period), we simply call
the method on the server proxy itself. The resulting output is:
$ python calclient.py |
XML-RPC is simpler than SOAP, and is very popular in open-source projects. It is an essential toolkit for any language or framework to offer these days, and so Python's new XML-RPC modules are a welcome addition. However, it does have its weaknesses, chief
of which is its support for character encodings, which shows an appalling bias towards English which seems out of place in these days when the importance of internationalization is well understood.
In the next installment we shall examine Python tools for another web services interface that has gained widespread popularity: RDF site summary (RSS).
- Participate in the discussion forum.
- Start your exploration of XML-RPC on the official home page. Thespecification is also a very easy read.
- For reference, use the official Python docs for the XML-RPC client and server modules.
- UserLand provides a XML-RPC interface for Current Time.
- Browse Useful Information Company's XML-RPC page for more sampleXML-RPC services.
- If you plan to do significant work using the protocol, do read and bookmark Eric Kidd'sXML-RPC HOWTO.
- Read Using XML-RPC for web services: Getting started with XML-RPC in Perl, by Joe Johnston for an introduction to XML-RPC, and the follow-upXML-RPC
Middleware. - And if XML-RPC doesn't cut it for you, don't forget our recent coverage of SOAP libraries for Python:Part 1,Part
2 andPart 3
Mike Olson is a consultant and co-founder of Fourthought Inc., a software vendor and consultancy specializing in XML solutions for enterprise knowledge management applications. Fourthought develops4Suite, an open source platform for XML middleware. You can contact Mr.
Olson atmike.olson@fourthought.com.
Uche Ogbuji is a consultant and co-founder of Fourthought Inc., a software vendor and consultancy specializing in XML solutions for enterprise knowledge management applications. Fourthought develops4Suite, open source platforms for XML middleware.Mr. Ogbuji is a Computer
Engineer and writer born in Nigeria, living and working in Boulder, Colorado, USA. You can contact Mr. Ogbuji atuche@ogbuji.net.
The Python web services developer: XML-RPC for Python的更多相关文章
- Python Web-第五周-Web Services and XML(Using Python to Access Web Data)
1.Web Service Overview 1.Data on the Web Python Dictionary 和 Java HashMap间需要建立一个桥梁,可以用XML或是JSON 2.XM ...
- 《Using Python to Access Web Data》 Week5 Web Services and XML 课堂笔记
Coursera课程<Using Python to Access Web Data> 密歇根大学 Week5 Web Services and XML 13.1 Data on the ...
- 基于soap 的 python web services 服务开发指南
文章大纲 序言 相关概念 SOA web services SOAP WSDL UDDI 环境搭建 我们使用 python 3.6 这个较新python 版本 服务端开发 客户端开发 suds-jur ...
- Web Services 中XML、SOAP和WSDL的一些必要知识
Web Services 是由xml来定义数据格式的,通过SOAP协议在各个系统平台中传输,那么接下来讨论下SOAP和WSDL的各自作用. SOAP和WSDL对Web Service.WCF进行深入了 ...
- Java EE (3) -- Java EE 6 Web Services Developer Certified Expert(1z0-897)
Create an SOAP web service in a servlet container Create a RESTful web service in a servlet containe ...
- python三大web框架Django,Flask,Flask,Python几种主流框架,13个Python web框架比较,2018年Python web五大主流框架
Python几种主流框架 从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等. Django: Python We ...
- Django,Flask,Tornado三大框架对比,Python几种主流框架,13个Python web框架比较,2018年Python web五大主流框架
Django 与 Tornado 各自的优缺点Django优点: 大和全(重量级框架)自带orm,template,view 需要的功能也可以去找第三方的app注重高效开发全自动化的管理后台(只需要使 ...
- 用jersey写 java restfull web services 输出xml格式数据
1 logic package com.toic.rest; import com.toic.model.Folder; import java.util.logging.Logger; import ...
- xml rpc SimpleXMLRPCServer [python]
SimpleXMLRPCServe 其实里面xml的概念不是很强,主要是rpc !不用关心什么xml . rpc 是就是远程调用,把函数什么的放到远程服务器上,本地调用就行了.用 SimpleXMLR ...
随机推荐
- iOS - Swift PList 数据存储
前言 直接将数据写在代码里面,不是一种合理的做法.如果数据经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低.因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据.如 ...
- SQL中char、varchar、nvarchar的区别(zhuan)
char char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符. nvarcha ...
- 【51nod】1376 最长递增子序列的数量
数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可能有很多个. ...
- Android lint 删除无用图片文件和配置文件
Android lint 删除无用.冗余的 配置文件和 图片资源 转载请注明 http://blog.csdn.net/aaawqqq?viewmode=contents Android项 ...
- 【ufldl tutorial】Convolution and Pooling
卷积的实现: 对于每幅图像,每个filter,首先从W中取出对应的filter: filter = squeeze(W(:,:,filterNum)); 接下来startercode里面将filter ...
- 常用的 文件 MIME类型
估计很多朋友对不同后缀的文件对应的MIME类型不熟悉(实际上这么多我也记不住), 所以将平常常见的一些文件后缀对应的MIME类型写了一个对照表,现在奉献给大家: .asx,video/x-ms-asf ...
- ManyToMany关联方式----
http://blog.csdn.net/sinat_18882775/article/details/51171427 好的博客 系列文章总结
- 如何部署Scrapy 到Scrapyd上?
安装上传工具 1.上传工具 scrapyd-client 2.安装方法: pip install scrapyd-client 3.上传方法: python d:\Python27\Scripts\s ...
- 使用 Subversion (SVN) 的方式来访问 Github(转)
[转至]:http://www.open-open.com/lib/view/open1340760267717.html
- Spring表达式语言 之 5.3 SpEL语法(拾肆)
5.3 SpEL语法 5.3.1 基本表达式 一.字面量表达式: SpEL支持的字面量包括:字符串.数字类型(int.long.float.double).布尔类型.null类型. 类型 示例 字 ...