【问题标题】:How to wrap a xmlrpc function call?如何包装 xmlrpc 函数调用?
【发布时间】:2013-06-22 05:46:10
【问题描述】:

我有一个简单的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'

如何使这段代码工作?

其他信息和限制:

  • 我已经尝试用functools.wraps(attr) 包裹wrapper,但没有成功。由于字符串 attr 没有属性 __name__ 我得到一个不同的错误
  • 我无法更改server.py 中定义的任何内容。
  • 上面的例子完全可以工作。
  • return wrapper 替换为return attr 不是解决方案 - 我需要在wrapper 中执行实际的xmlrpc 调用。
  • 我需要一个没有 3rd 方库的简单解决方案,标准 python 库都可以。

【问题讨论】:

  • 您能否更新异常以显示完整回溯?
  • 完成,并添加了 XMLRPC 实例化的缺失行...

标签: python wrapper xml-rpc xmlrpcclient


【解决方案1】:

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

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)

【讨论】:

  • 终于它似乎工作了。非常感谢。感谢您全天候 24/7 回答 python 问题,看来...
猜你喜欢
  • 1970-01-01
  • 2014-05-19
  • 2021-09-14
  • 2017-09-13
  • 1970-01-01
  • 2016-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多