This recipe demonstrates the creation of a simple XML-RPC server using the SimpleXMLRPCServer class. It requires either Python 2.2 or later or the XML-RPC package from PythonWare (http://www.pythonware.com/products/xmlrpc/index.htm) to run.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | # Server code
import SimpleXMLRPCServer
class StringFunctions:
def __init__(self):
# Make all of the Python string functions available through
# python_string.func_name
import string
self.python_string = string
def _privateFunction(self):
# This function cannot be called through XML-RPC because it
# starts with an '_'
pass
def chop_in_half(self, astr):
return astr[:len(astr)/2]
def repeat(self, astr, times):
return astr * times
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000))
server.register_instance(StringFunctions())
server.register_function(lambda astr: '_' + astr, '_string')
server.serve_forever()
# Client code
import xmlrpclib
server = xmlrpclib.Server('http://localhost:8000')
print server.chop_in_half('I am a confidant guy')
print server.repeat('Repetition is the key to learning!\n', 5)
print server._string('<= underscore')
print server.python_string.join(['I', 'like it!'], " don't ")
print server._privateFunction() # Will throw an exception
|
SimpleXMLRPCServer is a simple class that listens for HTTP requests, on a specified port, and dispatches any XML-RPC calls to either a registered instance or a registered function. The example above demonstates both usages.
Registering functions (as opposed to an instance) is necessary if you want to give your functions names beginning with '_' or containing characters not allowed in Python identifiers (Unicode characters, plus signs, etc.)
Note that dotted names (i.e. python_string.join) are correctly resolved for registered instances.
Threaded example. This isn't my code, I found it when I wanted to run an XMLRPC server in a separate thread:
More here:
http://www.codecomments.com/Python/message190478.html
http://www.python.org/doc/2.3.3/lib/module-SocketServer.html
Forking XML-RPC server. Similarly, you can invoke each XML-RPC method in a single process with code like this:
If using this code, remember that the methods can't rely on any shared global state, for example such as a dictionary used as a cache, because each method is run in a subprocess that does its work and then exits. Any changes to global variables or object attributes in the method won't be visible to the parent process.
2.4 doesn't allow dotted notation of functions. In this server code, __init__ has
lines and the client code has the
print server.python_string.join(['I', 'like it!'], " don't ")
line. These codes are intended to use the dotted notation of function that Python 2.4's xmlrpclib disallows to use in default so the client code raise an exception when the line is executed. You can choise from some options to make the client code line to work. they are: ・assign string functions FUNCNAME to self.python_string.FUNCNAME one bye one or by looping names of string functions. ・change the server code: server.register_instance(StringFunctions()) to: server.register_instance(StringFunctions(), allow_dotted_names = True) allows dotted notation of the function.
Error Message. This is just to confirm the previous post, and add the exception error message (so people like me find this comment faster through searches) if you use the recipe literally :
=Thomas
compression. (Disclaimer : I'm not a python expert in any way, just sharing...)
xmlrpc is great, easy, dynamic but is not effecient as binary methods (see "The Python Web services developer: Messaging technologies compared" at http://www.ibm.com/developerworks/library/ws-pyth9/).
For example, it can take minutes to transfer 100MB of data between client and server.
Therefore, I added compression, using http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/355486.
This shortened the transfer time to 15 seconds. Example server function (returns an arbitrary chunk of bytes, possibly with random values):
Example client side (request a 1MB chunk of bytes using 0x11 as default value for each byte (non random)).
Note that we originate from a python array at the server and end up with an array at the client.
Just my 2 cents :)
How do i set header while calling method at server side? I want to call a function named system.auth at server side while setting the header via:
import httplib httplib.HTTPConnection.putheader("AUTHORIZATION", "Basic %s"%encodestring("%s:%s" % (ustring,text_ucert)))