5

如何在 Python DBus 中实现异步方法?下面的一个例子:

class LastfmApi(dbus.service.Object):
    def __init__(self):
        bus_name = dbus.service.BusName('fm.lastfm.api', bus=dbus.SessionBus())
        dbus.service.Object.__init__(self, bus_name, '/')

    @dbus.service.method('fm.last.api.account', out_signature="s")
    def getUsername(self):
        ## How do I get this method done asynchronously ??
        ##  For example, this method should go off and retrieve the "username"
        ##  asynchronously. When this method returns, the "username" isn't available
        ##  immediately but will be made available at a later time.

我正在使用 Twisted 的 glib2 反应器。

更新:我知道这种行为是可以实现的——DBus 包括一个“串行”(唯一标识符)到方法调用,并且被调用的方法可以访问这个标识符,以便将“调用”与“回复”匹配。

4

1 回答 1

6

我还没有尝试过,但是阅读文档以dbus.service.method揭示async_callbacks参数。听起来好像有人使用此参数来提供异步结果。例如:

@dbus.service.method('fm.last.api.account', out_signature="s",
                     async_callbacks=("callback", "errback"))
def getUsername(self, callback, errback):
    reactor.callLater(3, callback, "alice")

相反,如果您有一个返回 Deferred 的 API,那么您可以轻松地将 Deferred 与这些回调关联:

d.addCallbacks(callback, errback)

就调用和响应之间的相关性而言,我假设所有的序列号处理都隐藏在dbus.service.method. 我怀疑使用该async_callbacks功能时传入的回调和 errback 函数要么是某个可调用类的实例,并且具有序列号作为属性,要么被定义为嵌套函数并关闭序列号。这样,当您调用其中一个时,它们可以确保将正确的值传递回连接,以将响应与原始请求相关联。

但是,这只是基于您提到的序列号和我实现各种异步系统的经验的稍微有根据的猜测。:) 阅读实施dbus.service.method可能会揭示实际策略而不会带来太多痛苦。

(好吧,我现在实际上去看了实现,不幸的是它相当复杂,当它到达一些在 C 级 dbus 绑定中定义的代码时,我失去了踪迹,这比我更深入一点有兴趣做。我仍然怀疑我上面描述的总体思路是正确的,但是实现的细节比我预期的要复杂。)

于 2010-01-26T20:47:01.807 回答