我有一个运行xmlrpc
的服务器,如下所示
from SimpleXMLRPCServer import SimpleXMLRPCServer
def add(x,y):
return x+y
server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(add, 'add.numbers')
server.serve_forever()
在以下代码中使用:
import xmlrpclib
class DeviceProxy(object):
def __init__(self, uri):
self.rpc = xmlrpclib.ServerProxy(uri)
def __getattr__(self, attr):
return getattr(self.rpc, attr)
original = DeviceProxy.__getattr__
def mygetattr(device, attr):
def wrapper(*args, **kw):
print('called with %r and %r' % (args, kw))
return original(device, attr)(*args, **kw)
return wrapper
DeviceProxy.__getattr__ = mygetattr
dev = DeviceProxy("http://localhost:8000/RPC2")
print dev.add.numbers(4,6)
正如您所看到的,Proxy
类包含xmlrpc
代理的原因超出了此问题的范围,通过__getattr__
方法转发任意调用。出于此问题范围之外的其他原因,我需要通过不同的方法将此__getattr__
方法换行/替换为例如打印出所调用函数的名称,参数等(参见相关问题here)。
但是这种方法不起作用,它会出现以下错误:
AttributeError: 'function' object has no attribute 'numbers'
当我
时,该示例按预期工作DeviceProxy.__getattr__
用函数
替换DeviceProxy.__getattr__
def dummy(instance,attr): return original(device,attr)
用零点名称替换xmlrpc
函数的名称(例如sum
而不是sum.numbers
)
您可以验证以下通过xmlrpc代理直接调用将按预期工作:
dev = xmlrpclib.ServerProxy("http://localhost:8000/RPC2")
print dev.add.numbers(4,6)
我的问题:如何解决我的问题,即如何能够正确地包装/覆盖DeviceProxy.__getattr__
以便能够看到所调用的函数,所有参数等,而无需在xmlrpc
中进行更改服务器或DeviceProxy
类?
答案 0 :(得分:0)
我可以在这里看到两个问题:
functools.wraps
来实现它。这应该有用
from functools import wraps
@wraps(original) # probably not needed, but sensible
def mygetattr(device, key):
attr = original(device, key)
if callable(attr):
@wraps(attr) # copy across __name__, __dict__ etc
def wrapper(*args, **kw):
print('called with %r and %r' % (args, kw))
return attr(*args, **kw)
return wrapper
else: # handle (or rather, don't) non-callable attributes
return attr