装饰DBUS方法

2 投票
1 回答
1103 浏览
提问于 2025-04-16 12:09

我正在尝试把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参数时就使用那个装饰器。

撰写回答