D-Bus Python service example

I found it quite frustrating to get started with D-Bus and the lack of working examples.

I found this bit of example somewhere, can’t remember the original source, sorry about that.

I’ll be using python3 and dbus-python for this example

Prerequisite

You’ll need:

  • python3
  • build-essential
  • libdbus-1-3
  • dbus-python

For debugging and getting a clearer picture of what’s happening, install also d-feet.

Code

#!/usr/bin/python3 from gi.repository import GLib import dbus import dbus.service from dbus.mainloop.glib import DBusGMainLoop class Example(dbus.service.Object): def __init__(self, object_path): super().__init__(dbus.SessionBus(), object_path) self._last_input = 1.0 @dbus.service.method(dbus_interface='com.example.Sample', in_signature='v', out_signature='s') def StringifyVariant(self, var): self.LastInputChanged(var) # emits the signal return str(var) @dbus.service.signal(dbus_interface='com.example.Sample', signature='v') def LastInputChanged(self, var): # run just before the signal is actually emitted # just put "pass" if nothing should happen self._last_input = var @dbus.service.method(dbus_interface='com.example.Sample', in_signature='', out_signature='v') def GetLastInput(self): return self._last_input if __name__ == '__main__': dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) name = dbus.service.BusName("com.example.Sample", dbus.SessionBus()) service = Example('/com/example/Sample') mainloop = GLib.MainLoop() print ("Running sample service.") mainloop.run()

chmod +x your python file and make run it.

Testing

To execute the method declared in the service, use the dbus-send command line utility.

dbus-send --session --dest="com.example.Sample" --type="method_call" --print-reply "/com/example/Sample" "com.example.Sample.GetLastInput"

From here you can either get the return value or some error.

The return value looks something like this.

method return time=1591277771.079203 sender=:1.139 -> destination=:1.144 serial=7 reply_serial=2 variant double 1

You can also get this time of error

Error org.freedesktop.DBus.Error.ServiceUnknown: The name org.example.Sample was not provided by any .service files

This one means 2 things either your service is not running or you made a mistake in the request.

Check first that your service in running. If it is then take a look at d-feet and correct your query

Another pitfall is to have multiple processes running at the same time. The new process is queued. So if you try to run a new modified instance and the behavior doesn’t match that’s another place to look

Now about the “The name org.example.Sample was not provided by any .service files“.

You can declare that service file yourself.

With root privilege, add com.example.Sample.service file in /usr/share/dbus-1/services/. The file name must match the service name

[D-BUS Service] Name=com.example.Sample Exec=/home/me/dbus_test/service.py

After adding this file any D-Bus request to our org.example.Sample service will automatically start it

/usr/share/dbus-1/system-services/ are for D-Bus service running on the system bus and opposed to session bus.

For system service, you also need to add a file defining the permissions for the service. I’ll get back to that at some points and post an example.

Leave a Reply

Your email address will not be published. Required fields are marked *