2010-01-26 14 views
5

Come implementare un metodo asincrono in Python DBus? Un esempio di seguito:Implementazione di un metodo asincrono in 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. 

Sto usando reattore glib2 Twisted.

Aggiornamento: So che questo comportamento è possibile implementare - DBus include una (identificatore unico) "di serie" per chiamate di metodo e il metodo chiamato ha accesso a questo identificatore al fine di corrispondere "chiamate" con "risposte" .

+0

Non è del tutto chiaro cosa vuoi ottenere qui. Cosa dovrebbe fare 'getUsername'? –

risposta

6

Non ho provato questo, ma leggendo la documentazione per dbus.service.method rivela il parametro async_callbacks. Sembra che uno usi questo parametro per fornire un risultato asincrono. Ad esempio:

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

Se, invece, si ha un'API che restituito un differita, allora si può facilmente associare il differita con queste callback:

d.addCallbacks(callback, errback) 

quanto riguarda la correlazione tra chiamata e risposta Va, presumo che tutta la gestione dei numeri di serie sia nascosta all'interno di dbus.service.method. Sospetto che le funzioni callback e errback che vengono passate quando si utilizza la funzione async_callbacks siano istanze di una classe che è chiamabile e che abbia il numero seriale come attributo, oppure che siano definite come funzioni annidate e che si chiudano sul numero seriale. In questo modo, quando si chiama uno di essi, è possibile assicurarsi di trasferire nuovamente il valore corretto alla connessione per associare la risposta alla richiesta originale.

Tuttavia, questa è solo un'ipotesi un po 'educata basata sulla menzione dei numeri seriali e sulla mia esperienza con l'implementazione di vari sistemi asincroni. :) Una lettura dell'implementazione di dbus.service.method probabilmente rivelerebbe la strategia attuale senza troppo dolore.

(Okay, in realtà sono andato a esaminare l'implementazione ora, e sfortunatamente è piuttosto complicato, e ho perso la traccia quando è arrivato a un codice definito nelle associazioni dbus di livello C, che è un po 'più di scavo Ho ancora il sospetto che l'idea generale che ho descritto sopra sia corretta, ma i dettagli dell'implementazione sono più complessi di quanto mi aspettassi.)

+0

Grazie Jean-Paul: come si fa la correlazione tra "metodo call" e "metodo return"? In DBus, quando viene chiamata una funzione "dbus_connection_send" (API C di basso livello), la funzione accetta un puntatore a un numero intero per passare l'identificativo univoco "seriale" al chiamante. Non vedo come ci si prende cura di qui. – jldupont

+0

Modificata la risposta per provare a coprire anche questo. –

+0

Paul: grazie per tutto il tuo impegno. Sulla base dei tuoi indizi, ho proseguito con il reverse engineering e ho capito: sembra che funzioni più o meno come descrivi. – jldupont