Recipe 15.3. Using XML-RPC with Medusa
Credit: Jeff Bauer
Problem
You need to establish a lightweight,
highly scalable, distributed processing system and want to use the
XML-RPC protocol.
Solution
Package
medusa lets you implement lightweight, highly
scalable, asynchronous (event-driven) network servers. An XML-RPC
handler is included in the Medusa distribution. Here is how you can
code an XML-RPC server with Medusa:
# xmlrpc_server.pyAnd here is a client script that accesses the server you just wrote:
from socket import gethostname
from medusa.xmlrpc_handler import xmlrpc_handler
from medusa.http_server import http_server
from medusa import asyncore
class xmlrpc_server(xmlrpc_handler):
# initialize and run the server
def _ _init_ _(self, host=None, port=8182):
if host is None:
host = gethostname( )
hs = http_server(host, port)
hs.install_handler(self)
asyncore.loop( )
# an example of a method to be exposed via the XML-RPC protocol
def add(self, op1, op2):
return op1 + op2
# the infrastructure ("plumbing") to expose methods
def call(self, method, params):
print "calling method: %s, params: %s" % (method, params)
if method == 'add':
return self.add(*params)
return "method not found: %s" % method
if _ _name_ _ == '_ _main_ _':
server = xmlrpc_server( )
# xmlrpc_client.py
from socket import gethostname
from xmlrpclib import Transport, dumps
class xmlrpc_connection(object):
def _ _init_ _(self, host=None, port=8182):
if host is None:
host = gethostname( )
self.host = "%s:%s" % (host, port)
self.transport = Transport( )
def remote(self, method, params=( )):
"" Invoke the server with the given method name and parameters.
The return value is always a tuple. ""
return self.transport.request(self.host, '/RPC2',
dumps(params, method))
if _ _name_ _ == '_ _main_ _':
connection = xmlrpc_connection( )
answer, = connection.remote("add", (40, 2))
print "The answer is:", answer
Discussion
This recipe demonstrates remote method calls between two machines (or
two processes, even on the same machine) using the XML-RPC protocol
and provides a complete example of working client/server code.XML-RPC is one of the easiest ways to handle distributed processing
tasks. There's no messing around with the low-level
socket details, nor is it necessary to write an interface definition.
The protocol is platform and language neutral. The XML-RPC
specification can be found at http://www.xml-rpc.com and is well worth
studying. It's nowhere as functionally rich as
heavyweight stuff like CORBA, but, to compensate, it
is much simpler!To run this recipe's Solution, you must download the
Medusa library from http://www.nightmare.com (the Python Standard
Library includes the asyncore and
asynchat modules, originally from Medusa, but not
the other parts of Medusa required for this recipe). With Medusa, you
implement an XML-RPC server by subclassing the
xmlrpc_handler class and passing an instance of
your class to the install_handler method of an
instance of http_server. HTTP is the
transport-level protocol used by the XML-RPC standard, and
http_server handles all transport-level issues on
your behalf. You need to provide only the handler part, by
customizing xmlrpc_handler through subclassing and
method overriding. Specifically, you must override the
call method, which the Medusa framework calls on
your instance with the name of the XML-RPC method being called, along
with its parameters, as arguments. This is exactly what we do in this
recipe, in which we expose a single XML-RPC method named
add which accepts two numeric parameters and returns
their sum as the method's result.This recipe's XML-RPC client uses
xmlrpclib in a more sophisticated way than Recipe 15.1, by accessing the
TRansport class explicitly. In theory, this
approach allows finer-grained control. However, this recipe does not
exert that kind of control, and it's rarely required
in XML-RPC clients that you actually deploy, anyway.
See Also
The xmlrpclib module is part of the Python
Standard Library and is documented in a chapter of the
Library Reference portion of
Python's online documentation. Medusa is at
http://www.nightmare.com.