|
|
 |
|
Title: A simple XML-RPC server
Submitter: Brian Quinlan
(other recipes)
Last Updated: 2001/10/13
Version no: 1.0
Category:
Web
|
|
3 vote(s)
|
|
|
|
Description:
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.
Source: Text Source
import SimpleXMLRPCServer
class StringFunctions:
def __init__(self):
import string
self.python_string = string
def _privateFunction(self):
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()
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()
Discussion:
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.
|
|
Add comment
|
|
Number of comments: 5
Threaded example, Duncan Gough, 2004/06/22
This isn't my code, I found it when I wanted to run an XMLRPC server in a separate thread:
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
pass
if __name__ == "__main__":
server = SimpleThreadedXMLRPCServer(("localhost", 8001))
server.register_instance(MyXMLRPCObject()) # register your distant Object here
server.serve_forever()
More here:
http://www.codecomments.com/Python/message190478.html
http://www.python.org/doc/2.3.3/lib/module-SocketServer.html
Add comment
Forking XML-RPC server, A.M. Kuchling, 2005/01/13
Similarly, you can invoke each XML-RPC method in a single process with
code like this:
import SocketServer
import SimpleXMLRPCServer
class ForkingXMLRPCServer (SocketServer.ForkingMixIn,
SimpleXMLRPCServer.SimpleXMLRPCServer):
pass
server = ForkingXMLRPCServer(("localhost", 8000))
# Register functions here...
server.serve_forever()
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.
Add comment
2.4 doesn't allow dotted notation of functions, KAMOSAWA Masao, 2006/04/29
In this server code, __init__ has
import string
self.python_string = string
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.
Add comment
Error Message, Thomas Herchenroeder, 2007/07/18
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 :
xmlrpclib.Fault: <Fault 1: '<type \'exceptions.Exception\'>:method "python_string.join" is not supported'>
=Thomas
Add comment
compression, Gal Aviel, 2007/07/23
(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):
from array import array
from random import randint
import zlib, base64
def get_data(self, default_byte_value=0x00,num_bytes=1024,use_rand=False):
data = array('B', [default_byte_value] * num_bytes )
if ( use_rand ):
for i in range(num_bytes):
data[i] = randint(0, 255)
data,csum = asciiCompress(buffer(data))
return data
Example client side (request a 1MB chunk of bytes using 0x11 as default value for each byte (non random)).
data = server.get_data(0x11,1 * 10**6,False)
data,csum = asciiDecompress(data)
arr = array('B',data)
Note that we originate from a python array at the server and end up with an array at the client.
Just my 2 cents :)
Add comment
|
|
|
|
|
 |
|