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呼び出し可能でシリアル番号を属性として持つクラスのインスタンスであるか、ネストされた関数として定義され、シリアル番号を閉じていると思われます。このようにして、それらのいずれかを呼び出すと、正しい値を接続に戻して、応答を元の要求に関連付けることができます。

ただし、これは、シリアル番号についてのあなたの言及と、さまざまな非同期システムの実装に関する私の経験に基づいた、少し知識に基づいた推測にすぎません。:) の実装を読むとdbus.service.method、実際の戦略があまり苦労せずに明らかになるでしょう。

(わかりました、私は実際に行って実装を見てきましたが、残念ながらかなり複雑で、C レベルの dbus バインディングで定義されているコードに到達したときにトレイルを失いました。これは私よりも少し掘り下げています。上で説明した一般的な考え方は正しいと思いますが、実装の詳細は予想以上に複雑です。)

于 2010-01-26T20:47:01.807 に答える