Как я реализую асинхронный метод в 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.
Я использую glib2 реактор Twisted.
Обновление: Я знаю, что это поведение возможно реализовать - DBus включает "сериал" (уникальный идентификатор) в вызовы метода, и вызываемый метод имеет доступ к этому идентификатору для соответствия "вызовам" "ответам".
Я не пробовал, но чтение документации на dbus.service.method
выявляет параметр async_callback
. Похоже, что этот параметр используется для получения асинхронного результата. Например:
@dbus.service.method('fm.last.api.account', out_signature="s",
async_callbacks=("callback", "errback"))
def getUsername(self, callback, errback):
reactor.callLater(3, callback, "alice")
Если вместо этого у вас есть API, который возвращает Deferred, то вы можете легко связать Deferred с этими обратными вызовами:
d.addCallbacks(callback, errback)
Что касается корреляции между вызовом и ответом, я предполагаю, что вся обработка серийных номеров скрыта внутри dbus.service.method
. Я подозреваю, что функции обратного вызова и errback, которые передаются при использовании функции async_callback
, являются либо экземплярами какого-то класса, которые вызываются и имеют серийный номер в качестве атрибута, либо определяются как вложенные функции и закрываются по серийному номеру. Таким образом, при вызове одной из них, они могут убедиться, что передают нужное значение обратно в соединение, чтобы связать ответ с оригинальным запросом.
Однако, это всего лишь слегка обоснованная догадка, основанная на вашем упоминании серийных номеров и моем опыте реализации различных систем асинхронизации :). Чтение реализации dbus.service.method
, вероятно, без лишней боли откроет реальную стратегию.
(Хорошо, на самом деле я пошел и посмотрел на реализацию сейчас, и, к сожалению, она довольно сложная, и я потерял след, когда добрался до какого-то кода, который определен в связках dbus.level на Си-уровне, что немного больше копает, чем мне интересно. Я до сих пор подозреваю, что общая идея, которую я описал выше, правильна, но подробности реализации оказались больше, чем я ожидал)
.