我有一个简单的xmlrpc服务器定义为(server.py):

from SimpleXMLRPCServer import SimpleXMLRPCServer

def foo():
    return "foo"

server = SimpleXMLRPCServer(("localhost", 1025))
server.register_introspection_functions()
server.register_function(foo, 'test.foo')
server.serve_forever()


客户端(client.py)实现如下:

import xmlrpclib

class XMLRPC(object):

    def __init__(self):
        self.xmlrpc = xmlrpclib.ServerProxy("http://localhost:1025/RPC2")

    def __getattr__(self, name):
        attr = getattr(self.xmlrpc, name)
        def wrapper(*args, **kwargs):
            result = attr(*args, **kwargs)
            return result
        return wrapper

xmlrpc = XMLRPC()
print xmlrpc.test.foo()


我想包装并执行对类xmlrpc中的XMLRPC服务器进行的每个调用。但是上面的工作示例给出了一个错误

Traceback (most recent call last):
  File "client.py", line 20, in <module>
    xmlrpc.test.foo()
AttributeError: 'function' object has no attribute 'foo'


如何使此代码起作用?

其他信息和约束:


我已经尝试用wrapper包装functools.wraps(attr)而不成功。由于字符串attr没有属性__name__,因此出现了另一个错误
我无法更改server.py中定义的任何内容。
上面的示例可以正常工作。
return wrapper代替return attr不是解决方案-我需要在xmlrpc中执行实际的wrapper调用。
我需要一个没有第三方库的简单解决方案,标准的python库是可以的。

最佳答案

您需要返回一个可调用对象。

XML-RPC代理返回一个可调用对象的实例,但也可以遍历该对象。因此,对于xmlrpc.test.foo(),您将xmlrpc.test包装在函数中。该函数对象没有foo属性,因为函数通常没有这样的属性。

而是返回一个代理对象; __call__挂钩使它成为可调用对象,就像一个函数一样:

class WrapperProxy(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped

    def __getattr__(self, name):
        attr = getattr(self.wrapped, name)
       return type(self)(attr)

    def __call__(self, *args, **kw):
        return self.wrapped(*args, **kw)

class XMLRPC(object):
    def __init__(self):
        self.xmlrpc = xmlrpclib.ServerProxy("http://localhost:1025/RPC2")

    def __getattr__(self, name):
        attr = getattr(self.xmlrpc, name)
        return WrapperProxy(attr)


或者,合并为一个对象:

class XMLRPCWrapperProxy(object):
    def __init__(self, wrapped=None):
        if wrapped is None:
            wrapped = xmlrpclib.ServerProxy("http://localhost:1025/RPC2")
        self.wrapped = wrapped

    def __getattr__(self, name):
        attr = getattr(self.wrapped, name)
       return type(self)(attr)

    def __call__(self, *args, **kw):
        return self.wrapped(*args, **kw)

关于python - 如何包装xmlrpc函数调用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17297169/

10-12 12:29