2010-01-26 17 views
5

¿Cómo implemento un método asíncrono en Python DBus? Un ejemplo a continuación:Implementación de un método asíncrono en 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. 

Estoy usando el reactor glib2 de Twisted.

actualización: Sé que este comportamiento es posible implementar - Enlace con el Bus incluye una "serie" (identificador único) a llamadas de método y el método de llamada tiene acceso a este identificador con el fin de que coincida con "llamadas" con "respuestas" .

+0

No está muy claro qué es lo que quiere lograr aquí. ¿Qué se supone que 'getUsername' debe hacer? –

Respuesta

6

No he intentado esto, pero al leer la documentación para dbus.service.method, se muestra el parámetro async_callbacks. Parece que uno usa este parámetro para proporcionar un resultado asincrónico. Por ejemplo:

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

Si, en cambio, tiene una API que devolvió un diferido, a continuación, se puede asociar fácilmente el diferido con estas devoluciones de llamada:

d.addCallbacks(callback, errback) 

En cuanto a la correlación entre llamada y respuesta va, supongo que todo el manejo del número de serie está oculto dentro de dbus.service.method. Sospecho que las funciones de devolución de llamada y errback que se transfieren cuando utiliza la característica async_callbacks son instancias de alguna clase que es invocable y tiene el número de serie como atributo, o bien se definen como funciones anidadas y se cierran sobre el número de serie. De esta forma, cuando llamas a uno de ellos, pueden asegurarte de pasar el valor correcto a la conexión para asociar la respuesta con la solicitud original.

Sin embargo, eso es solo una suposición ligeramente educada basada en su mención de los números de serie y mi experiencia con la implementación de varios sistemas asíncronos. :) Una lectura de la implementación de dbus.service.method probablemente revelaría la estrategia real sin demasiado dolor.

(De hecho, fui y miré la implementación ahora, y desafortunadamente es bastante complicado, y perdí el rastro cuando llegó a algún código que está definido en los enlaces de dbus de nivel C, que es un poco más excavar que estoy interesado en hacer. Todavía sospecho que la idea general que describí arriba es correcta, pero los detalles de la implementación son más complicados de lo que esperaba.)

+0

Gracias Jean-Paul: ¿cómo se realiza la correlación entre "método de llamada" y "método de retorno"? En DBus, cuando se llama a una función "dbus_connection_send" (API C de nivel bajo), la función toma un puntero a un entero para pasar el identificador único "serial" a la persona que llama. No veo cómo se soluciona esto aquí. – jldupont

+0

Editado la respuesta para tratar de cubrir eso también. –

+0

Paul: gracias por todo tu esfuerzo. Basándome en sus pistas, continué con ingeniería inversa y me di cuenta: parece que funciona más o menos de la manera que usted describe. – jldupont

Cuestiones relacionadas