19.6. Distributed Computing
There are many standards for distributed computing,
from simple Remote Procedure Call (RPC) ones to rich object-oriented ones such as CORBA. You can find many third-party Python modules that support these standards on the Internet.
The Python standard library supports both server and client use of a simple yet powerful standard known as XML-RPC.
For in-depth coverage of XML-RPC, I recommend the book Programming Web Services with XML-RPC, by Simon St.Laurent and Joe Johnson (O'Reilly). XML-RPC uses HTTP or HTTPS as the underlying transport and encodes requests and replies in XML. For server-side support, see "The Message Classes of the rfc822 and mimetools Modules" on page 573. Client-side support is supplied by module xmlrpclib.
The xmlrcplib module supplies a class ServerProxy, which you instantiate to connect to an XML-RPC server. An instance s of ServerProxy is a proxy for the server it connects to: you call arbitrary methods on s, and s packages the method name and argument values as an XML-RPC request, sends the request to the XML-RPC server, receives the server's response, and unpacks the response as the method's result. The arguments to such method calls can be of any type supported by XML-RPC:
Boolean
The built-in bool constants TRue and False
Integers, floating-point numbers, strings, arrays
Passed and returned as Python int, float, Unicode, and list values
Structures
Passed and returned as Python dict values whose keys must be strings
Dates
Passed as instances of class xmlrpclib.DateTime; value is represented in seconds since the epoch, as in module time (see Chapter 12).
Binary data
Passed as instances of class xmlrpclib.Binary; value is an arbitrary byte string
Module xmlrpclib supplies several classes.
Binary | class Binary(x)
x is a Python string of arbitrary bytes. b wraps the bytes as an XML-RPC binary object.
| DateTime | class DateTime(x)
x is the number of seconds since the epoch, as in module time, covered in "The time Module" on page 302.
| ServerProxy | class ServerProxy(uri, transport=None, encoding='utf-8', verbose=False, allow_none=False)
The uri string is normally the server's URL and may be of the form 'protocol://user:pass@host/...' to include a username and password for basic authentication; protocol is http or https, and you normally do not pass optional argument transport, allowing the module to pick the right transport for the given protocol. You may optionally pass optional argument encoding as the name of the 8-bit encoding to use, verbose as TRue to get verbose debugging information during the following XML-RPC operations, and allow_none as true to add None to the set of data types supported (this requires a server that sports a popular but not universal extension to the basic XML-RPC protocol).
If the server at the given uri supports introspection, s supplies an attribute s.system that in turn supplies three methods:
s.system.listMethods( )
Returns a list of strings, one per each method supported by the server.
s.system.methodSignature( name)
Returns a list of strings, each a signature of method name on the server. A signature string is composed of type names separated by commas: first the type of the return value, then the type of each argument. When method name has no defined signature, s.server.methodSignature(name) returns some object that is not a list.
s.system.methodHelp( name)
Returns a string with help about method name. The string can be either plain text or HTML. When the method name has no defined help, s.server.methodHelp(name) returns an empty string ''.
|
The following example uses xmlrpclib to access O'Reilly's Meerkat open wire service (see http://www.oreillynet.com/meerkat/ for more information about Meerkat) and displays a few recent news items about Python:
import xmlrpclib
proxy = xmlrpclib.ServerProxy(
'http://www.oreillynet.com/meerkat/xml-rpc/server.php')
results = proxy.meerkat.getItems({'search':'Python', 'num_items':7})
want_keys = 'title link description'.split( )
n = 0
for result in results:
n = n + 1
for key in want_keys:
print '%d. %s: %s' % (n, key.title( ), result.get(key))
print
|