Python XML-RPC Tutorial
I recently finally got around to looking into RPC and was pleasantly surprised with its ease of use. In fact, I wish I had investigated it a long time ago as there are a lot of networked applications that could be developed significantly faster using remote procedure call. Now that I’m so happy to be familiar with Python’s XML-RPC library, I thought I would write a quick and dirty tutorial that will get anyone started in just a couple minutes. The only prerequisite is that you are somewhat familiar with Python.
What is RPC?
RPC, which stands for Remote Procedure Call, is exactly what it sounds like. It allows the programmer to execute a function from another computer in almost the same way as would be done when executing the function locally. The end result is that the function gets called by the client, then it is executed on the server, and the output is sent to the client. As you can see, this can provide a great starting point for any program that requires client-server interaction.
What is XML-RPC?
XML-RPC is simply an implementation of RPC that uses XML. Since data about python objects will be transferred over the network, there needs to be some kind of data persistence system in place. This is where the XML part of XML-RPC comes in. In this case, the XML data is similar to pickling an object in Python. For the purposes of this tutorial, the underlying XML representation of the data will ignored.
Setting up:
All you’ll need to run this tutorial is a recent version of Python. The modules we will be using are called xmlrpclib and SimpleXMLRPCServer, both of which come preinstalled with python. Just to make sure, try running this in the python interpreter:
>>> import xmlrpclib >>> import SimpleXMLRPCServer >>>
If executing either of those lines raises an exception, then you may want to upgrade to a more recent version of python. You can do that here: Python website.
Now that we have that out of the way, let’s get to the fun stuff!
Writing the server:
Let’s start by making a simple Hello World application.
Call this file server.py:
import SimpleXMLRPCServer
# We are going to make the methods of this class callable
# from the client application over the network.
class HelloWorld:
def sayHello(self):
print 'hello'
return 'retval'
# Create an instance of our class
helloWorld = HelloWorld()
# Set the server to run on host localhost and port 8000
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000))
# Make our instance callable from the client
server.register_instance(helloWorld)
# Make the server actually start listening for requests
print "Server running..."
server.serve_forever()
All we’ve done here is created a class name HelloWorld whose methods can be remotely executed on port 8000. I have made the sayHello() method return a value and print to standard output to show that they will both be sent to the client, and that the standard output will not end up on the terminal of the server, just the client. If we want the method to return nothing (or None) then this line:
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000))
Would have to become:
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000), allow_none=True)
Writing the client:
The client is much easier. Here’s client.py:
import xmlrpclib
# Connect to localhost on port 8000
server = xmlrpclib.ServerProxy("http://localhost:8000")
# remotely execute teh sayHello() method
retval = server.sayHello()
# print the output
print retval
And there you have it! If you leave the server running in one terminal, and then run the client in another, it will output:
hello retval
This may not seem like a big deal, but the important part is that all the work is actually done on the server side. In this example there certainly wasn’t a lot of work to be done, but when it is necessary to have an operation be performed on another machine, RPC provides a quick method setting up a networked application. You could even write a simple web server in just a couple minutes using this method.
You write very well.
Comment by Abigail — Tuesday, October 28, 2008 @ 9:50 am