コールバックを D-Bus 信号に接続する「Listener」というクラスがあります。コールバックとシグナル名は、別のクラス「クライアント」によって提供されます。Client によって提供されるコールバックが、シグナルを受信したときに使用するコールバックとして connect_to_signal (dbus.Interface 上) に渡される場合、すべてが期待どおりに機能します。つまり、接続されたシグナルが受信されると、クラス Client のコールバック メソッドが呼び出されます。
ただし、信号を「傍受」してペイロードを評価してから Clients コールバックを呼び出したい場合は、次の例のように、ラムダ式を使用して connect_to_signal メソッドに渡すことができると考えました。
import dbus
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
from gi.repository import GObject
class Client(object):
def __init__(self):
bus = dbus.SystemBus()
obj = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
interface = dbus.Interface(obj, "org.freedesktop.UDisks")
listener = Listener()
signals_and_callbacks = {"DeviceAdded": self.device_added,
"DeviceChanged": self.device_changed}
listener.listen_to_signals(interface, signals_and_callbacks)
def device_added(self, payload):
print "in device_added ", payload
def device_changed(self, payload):
print "in device_changed ", payload
class Listener(object):
def listen_to_signals(self, interface, signals_and_callbacks):
for signal, callback in signals_and_callbacks.items():
cb = lambda x: self.signal_cb(x, callback)
interface.connect_to_signal(signal, cb)
def signal_cb(self, opath, subscriber_cb):
print subscriber_cb
subscriber_cb(opath)
if __name__ == "__main__":
client = Client()
mainloop = GObject.MainLoop()
mainloop.run()
しかし、これは意図したとおりには機能しません。シグナルが接続されます。この場合、コードは「DeviceAdded」と「DeviceChanged」の両方に反応しますが、最後に追加されたコールバックのみが呼び出されます。シグナルを 1 つだけ接続すると、動作は期待どおりになりますが、ラムダ式をコールバックとして渡して複数のシグナルを接続するとすぐに、両方のシグナルが最後に追加されたコールバックへの呼び出しをトリガーします。
ここで何が起こっているのか誰にも分かりませんか?