装饰DBUS方法
我正在尝试把DBUS的异步方法调用和Twisted的Deferred结合起来,但在调整通常的DBUS服务方法装饰器时遇到了麻烦。
如果你想使用DBUS的异步回调方式,你可以这样做:
class Service(dbus.service.Object):
@dbus.service.method(INTERFACE, async_callbacks=('callback', 'errback'))
def Resources(self, callback, errback):
callback({'Magic' : 42})
在一些地方,我只是把这两个方法包裹在一个Deferred里,所以我想创建一个装饰器来帮我完成这个工作:
def twisted_dbus(*args, **kargs):
def decorator(real_func):
@dbus.service.method(*args, async_callbacks=('callback', 'errback'), **kargs)
def wrapped_func(callback, errback, *inner_args, **inner_kargs):
d = defer.Deferred()
d.addCallbacks(callback, errback)
return real_func(d, *inner_args, **inner_kargs)
return wrapped_func
return decorator
class Service(dbus.service.Object):
@twisted_dbus(INTERFACE)
def Resources(self, deferred):
deferred.callback({'Magic' : 42})
然而,这样做不行,因为这个方法是绑定的,并且需要第一个参数,这导致了这个错误信息:
$ python service.py
Traceback (most recent call last):
File "service.py", line 25, in <module>
class StatusCache(dbus.service.Object):
File "service.py", line 32, in StatusCache
@twisted_dbus(INTERFACE)
File "service.py", line 15, in decorator
@dbus.service.method(*args, async_callbacks=('callback', 'errback'), **kargs)
File "/usr/lib/pymodules/python2.6/dbus/decorators.py", line 165, in decorator
args.remove(async_callbacks[0])
ValueError: list.remove(x): x not in list
我可以在内部函数那里添加一个额外的参数,像这样:
def twisted_dbus(*args, **kargs):
def decorator(real_func):
@dbus.service.method(*args, async_callbacks=('callback', 'errback'), **kargs)
def wrapped_func(possibly_self, callback, errback, *inner_args, **inner_kargs):
d = defer.Deferred()
d.addCallbacks(callback, errback)
return real_func(possibly_self, d, *inner_args, **inner_kargs)
return wrapped_func
return decorator
但这看起来……嗯,有点傻。特别是如果我想导出一个没有绑定的方法。
那么,能让这个装饰器正常工作吗?
1 个回答
0
为什么这样做不好呢?你已经假设第一个位置参数(在self之后)是一个Deferred对象。那为什么假设第一个位置参数是self会更糟呢?
如果你还想支持自由函数(就是不属于任何类的函数),那么可以写一个新的装饰器,当你确定没有self参数时就使用那个装饰器。