1

( )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 ライブラリは問題ありません。
4

1 に答える 1

4

代わりに呼び出し可能なオブジェクトを返す必要があります。

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)

または、1 つのオブジェクトにマージされます。

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)
于 2013-06-25T12:33:32.337 に答える