Fork me on GitHub

xmlrpc con Python

July 30, 2013

XML-RPC es un protocolo de llamada a procedimiento remoto que usa XML para codificar los datos y HTTP como protocolo de transmisión de mensajes.

O sea, es un protocolo que te permite hacer llamadas a funciones en otra computadora independientemente del lenguaje que uses de un lado y de otro. Y lo mejor de todo es que la parte del XML es transparente así que no hay que lidiar con este feo formato. XML-RPC fue diseñado para ser tan simple como fuera posible, de hecho en el sitio xmlrpc.scripting.com puede leerse la siguiente cita:

"Does distributed computing have to be any harder than this? I don't think so."

Crear un servicio xmlrpc con Python es sencillo

#server.py
from SimpleXMLRPCServer import SimpleXMLRPCServer
import os

addr = ('127.0.0.1', 5000)
server = SimpleXMLRPCServer(addr)
server.register_function(os.listdir)

try:
    print("Listening on %s:%s" % addr)
    print("Use Control-C to exit")
    server.serve_forever()
except KeyboardInterrupt:
    print("Exiting")

La función que exportamos es os.listdir pero puede ser cualquier otra. Así que levantemos nuestro server

$ python server.py 
Use Control-C to exit
Listening on 127.0.0.1:5000

Ahora usemos el servicio. Para eso abrimos una consola de Python y escribimos

>>> import xmlrpclib
>>> proxy =  xmlrpclib.ServerProxy('http://127.0.0.1:5000')
>>> proxy.listdir('/home')
['sysop', 'media', 'xleo']

Fácil, no? Aquí va otro ejemplo exportando los métodos de un objeto y haciendo cambios en el servidor:

#server.py 
from SimpleXMLRPCServer import SimpleXMLRPCServer
from datetime import datetime

class Logger:

    def __init__(self):
        self.logs = []

    def logging(self, message):
        """Adds a new message to logs list.
        """
        log = (datetime.now(), message)
        self.logs.append(log)
        return log

    def tail(self, n=10):
        """Returns the last n messages. Default=10.
        """
        if len(self.logs) > n:
            return self.logs[-n:]
        else:
            return self.logs

addr = ('127.0.0.1', 5000)
server = SimpleXMLRPCServer(bind)
server.register_instance(Logger())
server.register_introspection_functions()

try:
    print("Listening on %s:%s" % bind)
    print("Use Control-C to exit")
    server.serve_forever()
except KeyboardInterrupt:
    print("Exiting")

Levantamos el servicio y desde una consola de Python probamos lo siguiente

>>> import xmlrpclib
>>> proxy = xmlrpclib.ServerProxy('http://127.0.0.1:5000')
>>> proxy.system.listMethods()
['logging', 'system.listMethods', 'system.methodHelp', 'system.methodSignature', 'tail']
>>> proxy.system.methodHelp('logging')
'Adds a new message to logs list.'
>>> import time 
>>> for i in range(5):
...   proxy.logging("Message %d" % i)
...   time.sleep(1)
... 
[<DateTime '20130730T17:25:12' at b6fd9b6c>, 'Message 0']
[<DateTime '20130730T17:25:13' at b6fe444c>, 'Message 1']
[<DateTime '20130730T17:25:14' at b6fe438c>, 'Message 2']
[<DateTime '20130730T17:25:15' at b6fe432c>, 'Message 3']
[<DateTime '20130730T17:25:16' at b6fe440c>, 'Message 4']
>>> proxy.system.methodHelp('tail')
'Returns the last n messages. Default=10.'
>>> proxy.tail(2)
[[<DateTime '20130730T17:25:15' at b6fe450c>, 'Message 3'], [<DateTime '20130730T17:25:16' at b6fd9bac>, 'Message 4']]

Referencias

Python