在Python DBus中实现异步方法

jld*_*ont 5 python asynchronous dbus twisted

如何在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.
Run Code Online (Sandbox Code Playgroud)

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

更新:我知道可以实现此行为 - DBus包含方法调用的"序列"(唯一标识符),并且被调用方法可以访问此标识符以匹配"调用"和"回复".

Jea*_*one 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")
Run Code Online (Sandbox Code Playgroud)

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

d.addCallbacks(callback, errback)
Run Code Online (Sandbox Code Playgroud)

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

然而,基于您提及的序列号以及我实现各种异步系统的经验,这只是一个稍微受过教育的猜测.:)阅读实施dbus.service.method可能会揭示实际的策略而不会太痛苦.

(好吧,我实际上现在去看看实现,不幸的是它相当复杂,当我得到一些在C级dbus绑定中定义的代码时,我失去了踪迹,这比我的挖掘要多一点我仍然怀疑上面描述的一般想法是正确的,但实施的细节比我预期的要多得多.)