11.6 通过XML-RPC实现简�的远程调用¶

问题¶

你想找到一个简�的方�去执行�行在远程机器上�的Python程�中的函数或方法。

解决方案¶

实现一个远程方法调用的最简�方�是使用XML-RPC。下�我们演示一下一个实现了键-值存储功能的简��务器:

from xmlrpc.server import SimpleXMLRPCServer

class KeyValueServer:
    _rpc_methods_ = ['get', 'set', 'delete', 'exists', 'keys']
    def __init__(self, address):
        self._data = {}
        self._serv = SimpleXMLRPCServer(address, allow_none=True)
        for name in self._rpc_methods_:
            self._serv.register_function(getattr(self, name))

    def get(self, name):
        return self._data[name]

    def set(self, name, value):
        self._data[name] = value

    def delete(self, name):
        del self._data[name]

    def exists(self, name):
        return name in self._data

    def keys(self):
        return list(self._data)

    def serve_forever(self):
        self._serv.serve_forever()

# Example
if __name__ == '__main__':
    kvserv = KeyValueServer(('', 15000))
    kvserv.serve_forever()

下�我们从一个客户端机器上��访问�务器:

>>> from xmlrpc.client import ServerProxy
>>> s = ServerProxy('http://localhost:15000', allow_none=True)
>>> s.set('foo', 'bar')
>>> s.set('spam', [1, 2, 3])
>>> s.keys()
['spam', 'foo']
>>> s.get('foo')
'bar'
>>> s.get('spam')
[1, 2, 3]
>>> s.delete('spam')
>>> s.exists('spam')
False
>>>

讨论¶

XML-RPC �以让我们很容易的构造一个简�的远程调用�务。你所需��的仅仅是创建一个�务器实例, 通过它的方法 register_function() �注册函数,然�使用方法 serve_forever() �动它。 在上�我们将这些步骤放在一起写到一个类中,�够这并�是必须的。比如你还�以�下�这样创建一个�务器:

from xmlrpc.server import SimpleXMLRPCServer
def add(x,y):
    return x+y

serv = SimpleXMLRPCServer(('', 15000))
serv.register_function(add)
serv.serve_forever()

XML-RPC暴露出�的函数�能适用于部分数�类型,比如字符串�整形�列表和字典。 对于其他类型就得需��些�外的功课了。 例如,如果你想通过 XML-RPC 传递一个对象实例,实际上�有他的实例字典被处�:

>>> class Point:
...     def __init__(self, x, y):
...             self.x = x
...             self.y = y
...
>>> p = Point(2, 3)
>>> s.set('foo', p)
>>> s.get('foo')
{'x': 2, 'y': 3}
>>>

类似的,对于二进制数�的处�也跟你想象的�太一样:

>>> s.set('foo', b'Hello World')
>>> s.get('foo')
<xmlrpc.client.Binary object at 0x10131d410>

>>> _.data
b'Hello World'
>>>

一般�讲,你�应该将 XML-RPC �务以公共API的方�暴露出�。 对于这�情况,通常分布�应用程�会是一个更好的选择。

XML-RPC的一个缺点是它的性能。SimpleXMLRPCServer 的实现是�线程的, 所以它�适�于大型程�,尽管我们在11.2�节中演示过它是�以通过多线程�执行的。 �外,由于 XML-RPC 将所有数�都�列化为XML格�,所以它会比其他的方��行的慢一些。 但是它也有优点,这�方�的编��以被�大部分其他编程语言支�。 通过使用这�方�,其他语言的客户端程�都能访问你的�务。

虽然XML-RPC有很多缺点,但是如果你需�快速构建一个简�远程过程调用系统的�,它�然值得去学习的。 有时候,简�的方案就已�足够了。