Recipe 15.3. Using XML-RPC with MedusaCredit: Jeff Bauer ProblemYou need to establish a lightweight, highly scalable, distributed processing system and want to use the XML-RPC protocol. SolutionPackage 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.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): # 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( ) And here is a client script that accesses the server you just wrote: # 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 DiscussionThis 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 AlsoThe 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. |