Credit: Jeff Bauer
The medusa
package lets you implement lightweight,
highly scalable servers, even with old versions of Python. An XML-RPC
handler is included in the Medusa distribution. Here is how you code
a server with Medusa:
# xmlrpc_server.py 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): # initializes and runs 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 "call method: %s, params: %s" % (method, str(params)) if method == 'add': return apply(self.add, params) return "method not found: %s" % method if _ _name_ _ == '_ _main_ _': server = xmlrpc_server( )
And here is an
xmlrpclib
-based client of this server:
# xmlrpc_client.py from socket import gethostname from xmlrpclib import Transport, dumps class xmlrpc_connection: 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=( )): """ remote invokes the server with the method name and an optional set of parameters. The return value is always a tuple. """ response = self.transport.request(self.host, '/RPC2', dumps(params, method)) return response if _ _name_ _ == '_ _main_ _': connection = xmlrpc_connection( ) (answer,) = connection.remote("add", (40, 2)) print "The answer is:", answer
This recipe demonstrates remote method calls between two machines (or two processes, even on the same machine) using the XML-RPC protocol. A complete example of working client/server code is provided. 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.
With Medusa (http://www.nightmare.com), 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,
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.
The sample XML-RPC client uses xmlrpclib
in a more
sophisticated way than Recipe 13.2 by using
the Transport
class explicitly. This lets you see
what happens under the covers of an XML-RPC method call a bit more
transparently and also lets you control things in a finer-grained
way, although we don’t use that fine-grained-control
potential in this recipe (and you will need it only rarely in XML-RPC
clients that you actually deploy, anyway).
xmlrpclib
can also be used on its own, without
separately downloading and installing Medusa, and comes with similar
client and server program examples. However, the asynchronous
operation of Medusa can significantly enhance performance,
particularly scalability. Medusa (and asyncore
and
asynchat
) are applicable to client- and
server-side programming, but this recipe does not use the
asynchronous approach in its example client, only in its example
server. Of course, the benefits of the asynchronous approach come
when a program does several network operations at once (in such
cases, asynchronous Medusa operations can give you substantial
performance benefits when compared to alternatives such as
multiprocessing and multithreading). This is almost always the case
for servers, which need to be able to field several requests arriving
simultaneously from different clients. It’s
certainly not unheard of for clients, too, if the client needs to
make several requests at once.
The XML-RPC (xmlrpclib
) library ships with recent
versions of Python; if it isn’t in your version of
Python, you can get it from http://www.pythonware.com/products/xmlrpc/;
the Medusa library at http://www.nightmare.com; recent Python
releases include the asyncore
and
asynchat
modules from Medusa as parts of the
Python standard library (not, however, other parts of Medusa, such as
xmlrpc_handler
).
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.