Skip to main content
 首页 » 编程设计

python之装饰 DBUS 方法

2025年05月04日7webabcd

我正在尝试将 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}) 

然而,这不起作用,因为该方法已绑定(bind)并采用第一个参数,导致此回溯:

$ 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 

但这似乎……嗯,愚蠢。特别是如果出于某种原因,我想导出一个非绑定(bind)方法。

那么有没有可能让这个装饰器起作用呢?

请您参考如下方法:

为什么会变笨?您已经假设您知道第一个位置参数(在 self 之后)是一个 Deferred。为什么假设您知道真正的第一个位置参数是 self 更愚蠢?

如果您还想支持自由函数,那么编写另一个装饰器并在您知道没有 self 参数时使用它。