.zugiart
Software Engineering, buddhism, and everything else in between.
  • Blog
    • Thoughts
    • Tech
  • About
  • Notes
    • Business Analysis
    • Chinese tea
    • Nokia n900
    • Programming
      • Linux Ubuntu Desktop Guide (9.10)
      • Linux Ubuntu Server setup
      • Python Programming
    • Sun Tzu – Art Of War
      • Chapter 1 – Laying Plans
      • Chapter 2 – Waging War
    • Tao Te Ching
      • Chapter 1-6
    • TED.com
      • TEDxMelbourne 2
      • TEDxMelbourne3
Browse: Home / geeky / Python XML-RPC

Python XML-RPC

By zen on August 12, 2009

I’ve added this snippets into my python notes. Here they are for convenience.

Dynamic Xml-Rpc server

This server code will use python “reflection” to publish all methods whose name are prefixed with PREFIX. In this case, the prefix is xmlrpc_, so all methods within this server such as xmlrpc_hello, will get published. The code already uses options, so it can be easily started like so:

python server.py –host=$HOSTNAME –port=portNum

Server skeleton code

import sys
from optparse import OptionParser
from SimpleXMLRPCServer import SimpleXMLRPCServer
 
class DynamicXMLRPCServer(SimpleXMLRPCServer):
    """
    An XMLRPC server that will register all function whose name are prefixed with PREFIX via xml-rpc
    Zen Sugiarto - 2011
    """
 
    # this is the prefix used by this sever to decide whether a given method should be published over xml-rpc or not.
    PREFIX="xmlrpc_"
 
    # constructor
    def __init__(self, params):
        self.params=params
        self.host=params['host']
        self.port=params['port']
        SimpleXMLRPCServer.__init__(self,(self.host, self.port))
        # register all xmlrpc_ functions over xml-rpc
        for name in dir(self):
            if name[:len(DynamicXMLRPCServer.PREFIX)] == DynamicXMLRPCServer.PREFIX:
                function=getattr(self,name)
                print "registering function: %s as %s " % ( name, name[len(DynamicXMLRPCServer.PREFIX):] )
                self.register_function(function, name[len(DynamicXMLRPCServer.PREFIX):])
 
    # note: xmlrpc_ prefix is used by this server to mark that this function will be published
    def xmlrpc_hello(self,msg):
        """
        A simple hello function used for simple ping check. 
        @param msg - msg to pass to hello
        @return dictionary {"hello":msg}
        """
        return {"hello":msg}
 
    def xmlrpc_describe(self):
        """
        Retrieves the description/documentation of available functions within this service.
        by the grace of python's .__doc__ object.
        @return dictionary of the following format
        { 
            'function_name' : 'documentation/description of that function '} 
        } 
        """
        metaDescription={}
        for name in dir(self):
            if name[:len(DynamicXMLRPCServer.PREFIX)] == DynamicXMLRPCServer.PREFIX:
                function=getattr(self,name)
                metaDescription[name[len(DynamicXMLRPCServer.PREFIX):]]=function.__doc__
        return metaDescription;
 
    def xmlrpc_yourFunction(self):
        """
        Put in more function here!~
        """
        print "IMPLEMENT ME"
 
def main():
    """ main method """
    parser = OptionParser(""" 
        Template service object - please put your comment in here
        """)
    parser.add_option("--host", dest="host", help="hostname to publish the service against")
    parser.add_option("--port", dest="port", help="port number to use")
    (options, args) = parser.parse_args()
 
    if( options.host == None or options.port == None ):
        print "insufficient options provided. try --help"
        sys.exit(1);
 
    server = DynamicXMLRPCServer({'host':options.host,'port':int(options.port)})
    server.serve_forever()
 
if __name__ == "__main__":
    main()

Dynamic XML-RPC Client

This will invoke Hello world function via xml-rpc, this is as simple as it gets

import xmlrpclib
print xmlrpclib.ServerProxy("http://localhost:8000/").hello("zen")

But this is even better: this is a client that will allow you to connect to any xml-rpc service (yes, even java ones in xml-rpc) and call any function as long as you know its signature.

import xmlrpclib
import readline
import cmd
import traceback
import pprint
import datetime
from optparse import OptionParser
import sys
 
class XmlRpcClientConsole(cmd.Cmd): 
    """
    Generic xml rpc client console, works with any xml rpc service
    """
    def __init__(self, url):
        cmd.Cmd.__init__(self)
        self.url = url;
        self.server = xmlrpclib.ServerProxy(url)
        self.pp = pprint.PrettyPrinter(indent=2)
        self.updatePrompt()
 
    def updatePrompt(self):
        self.prompt = "\n[%s] %s\nxmlrpc >> " % (datetime.datetime.now().strftime("%Y.%m.%d %H:%M:%S"),self.url)
 
    def default(self, line):
        try:
            result=None
            exec("result=self.server.%s" % (line))
            self.pp.pprint(result) # default formatter: pretty print the resultant data
        except Exception, ex:
            traceback.print_exc(ex)
        print; self.updatePrompt()
 
    def do_help(self,line):
        print
        print "-------------------------------------"
        print "GENERIC XML RPC CLIENT CONSOLE - HELP"
        print "-------------------------------------"
        print
        print "Simply type in the function name on the xml-rpc service end, like you would"
        print "on any good ol' python program. For example, if the other side has a method"
        print "called helloWorld(strparam), you can invoke it like so:"
        print
        print "... xmlrpc >> helloWorld('hello zen')"
        print
        print "the client is therefore completely transparent and exposes the full capabilities"
        print "of the server end. have fun." # -zen
        print 
 
def main():
    parser = OptionParser("""Generic XML RPC Client console""")
    parser.add_option("--url", dest="url", help="The XML RPC service URL to connect")
    parser.add_option("--cmd", dest="cmd", help="A one-off command to execute")
    (options, args) = parser.parse_args()
 
    if options.url == None :
        parser.print_help()
        sys.exit(1)
 
    console = XmlRpcClientConsole(options.url)
    if options.cmd != None :
        # run the cmd and bomb out
        console.default(options.cmd)
        sys.exit(0)
    else:
        print "for help using the console, type 'help'"
        # enter into cmd loop for interactive session
        console.cmdloop()
 
if __name__ == "__main__":
    main()

Example

Starting the server:

python server.py --host=localhost --port=6666 

Starting the client in console mode:

python client.py --url=http://localhost:6666 

Within the console:

[2011.06.22 11:31:25] http://localhost:6666
xmlrpc >> hello("zen")
{ 'hello': 'zen'}

Posted in geeky | Tagged python, rpc, xml | Leave a response

apache/bash/buddhism/classical/compassion/death/deviantart/distributed systems/eclipse/enlightenment/firefox/global crisis/hosting/japan/java/job/life/linux/literature/music/n900/notes/oracle/philiosophy./photography/poetry/programming/proxy/python/refactor/religion/roundup/rpc/science/software engineering/ted.com/tedxmelbourne/twitter/unsustainability/wallpaper/wisdom/wordpress/work/xml/xml-rpc

« Previous Next »

{ last word

  • jump chess is an interesting game. it teaches one about the importance of having an open mind. There are no fixed strategy in jump chess.3 days ago
  • it's that time of the day again. #eveningdelight gotta love jump chess! http://t.co/VkBjYnR93 days ago
  • #eveningdelight a game of jump chess, green tea ice cream and cakes http://t.co/mAhsLmeG4 days ago

{ search

Copyright © 2012 Zenikko Sugiarto. Powered by Wordpress