4126
Comment:
|
5690
Add information about the dasbus library
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
The [[http://www.freedesktop.org/wiki/Software_2fdbus|D-Bus library]] is a messaging library used by the GNOME desktop for interprocess communication. | The [[http://www.freedesktop.org/wiki/Software/dbus|D-Bus library]] is a messaging library used by various desktop environments (GNOME, KDE, etc) for interprocess communication. |
Line 3: | Line 3: |
There's a Python binding for it, but documentation is non-existent so I've collected these examples in hopes that they'll be useful and that people will update them as needed. | There are multiple Python bindings for DBus: |
Line 5: | Line 5: |
''Warning'': the D-Bus APIs change a lot, breaking code. These examples were run with version 0.60 of the Python interface (0.60-6ubuntu8, on Ubuntu Dapper); they probably won't run on other versions. | * GDbus and QtDbus are wrappers over the C/C++ APIs of GLib and Qt * [[https://github.com/LEW21/pydbus|pydbus]] is a modern, pythonic API with the goal of being as invisible a layer between the exported API and its user as possible * [[https://github.com/rhinstaller/dasbus|dasbus]] is a Python3-only alternative to pydbus with additional features and better flexibility * [[https://dbus.freedesktop.org/doc/dbus-python/|dbus-python]] is a legacy API, built with a deprecated dbus-glib library, and involving a lot of type-guessing (despite "explicit is better than implicit" and "resist the temptation to guess"). * [[https://pypi.python.org/pypi/txdbus|txdbus]] is a native Python implementation of the D-Bus protocol for the Twisted networking framework. |
Line 7: | Line 11: |
This [[http://thaiopensource.org/development/suriyan/wiki/DbusNotes|draft tutorial]] is the clearest introduction to D-Bus that I've seen. | See also: [[https://www.freedesktop.org/wiki/Software/DBusBindings/#python|DBusBindings]] on Freedesktop wiki. |
Line 9: | Line 13: |
The `dbus-viewer` program lets you browse through the services and interfaces available on your system. | The `dbus-viewer` and `qdbusviewer` programs let you browse through the services and interfaces available on your system. |
Line 11: | Line 15: |
= Introspection = | = pydbus = For more information see [[https://github.com/LEW21/pydbus/blob/master/README.rst|pydbus's Readme]]. |
Line 13: | Line 18: |
== Introspection == | |
Line 14: | Line 20: |
# You must initialize the gobject/dbus support for threading # before doing anything. import gobject gobject.threads_init() from dbus import glib glib.init_threads() # Create a session bus. import dbus bus = dbus.SessionBus() |
from pydbus import SessionBus bus = SessionBus() |
Line 27: | Line 24: |
remote_object = bus.get_object("org.freedesktop.DBus", # Connection name "/org/freedesktop/DBus" # Object's path ) |
remote_object = bus.get( "org.freedesktop.DBus", # Bus name "/org/freedesktop/DBus" # Object path ) |
Line 34: | Line 32: |
print remote_object.Introspect() | print (remote_object.Introspect()[0]) |
Line 36: | Line 34: |
Output: | |
Line 37: | Line 36: |
Output: {{{Introspection data: |
{{{ Introspection data: |
Line 57: | Line 56: |
If you get any of the connection or object names wrong, the exceptions you get are very obscure. For example, when I add an incorrect trailing slash to the object in the example above (making "/org/freedesktop/DBus/"), the exceptions are: {{{8223: arguments to dbus_message_new_method_call() were incorrect, assertion "_dbus_check_is_valid_path (path)" failed in file dbus-message.c line 797. This is normally a bug in some application using the D-BUS library. 8223: arguments to dbus_message_set_destination() were incorrect, assertion "message != NULL" failed in file dbus-message.c line 2728. This is normally a bug in some application using the D-BUS library. 8223: arguments to dbus_connection_send_with_reply() were incorrect, assertion "message != NULL" failed in file dbus-connection.c line 2430. This is normally a bug in some application using the D-BUS library. |
== Calling an interface method == After executing the introspection example: |
Line 65: | Line 59: |
Traceback (most recent call last): File "/home/amk/db.py", line 19, in ? data = remote_object.Introspect() File "/usr/lib/python2.4/site-packages/dbus/proxies.py", line 201, in __getattr__ self._pending_introspect.block() AttributeError: 'NoneType' object has no attribute 'block' |
{{{ print(remote_object.ListNames()[0]) }}} Output: {{{ ['org.freedesktop.DBus', 'org.freedesktop.Notifications', 'org.freedesktop.PowerManagement', ':1.8', ':1.9', 'org.kde.kaccess', 'org.kde.kded', 'org.kde.StatusNotifierItem-655-1', 'org.freedesktop.systemd1', 'org.ktorrent.ktorrent', 'org.kde.StatusNotifierItem-656-1', 'org.kde.konversation', 'org.pulseaudio.Server', 'org.kde.KScreen', 'org.kde.krunner', 'org.kde.konsole', ':1.40', 'org.a11y.Bus', ':1.41', ':1.42', ':1.20', ':1.43', 'org.kde.klauncher5', ':1.21', ':1.23', 'org.kde.dolphin-3012', 'org.freedesktop.PowerManagement.Inhibit', 'org.kde.Solid.PowerManagement', ':1.24', ':1.25', ':1.49', 'org.kde.kmix', 'org.kde.screensaver', 'org.kde.KWin', 'org.bluez.obex', ':1.29', 'ca.desrt.dconf', 'org.kde.kgpg', 'org.freedesktop.ScreenSaver', 'org.kde.plasmashell', 'org.kde.plasmanetworkmanagement', 'org.kde.StatusNotifierItem-666-1', 'org.kde.kglobalaccel', 'org.freedesktop.FileManager1', 'org.kde.kwalletd5', 'org.PulseAudio1', 'org.kde.polkit-kde-authentication-agent-1', ':1.93', 'org.kde.kded5', 'org.kde.ActivityManager', 'org.kde.keyboard', 'org.kde.kate-3030', ':1.31', 'org.kde.kuiserver', ':1.32', ':1.55', ':1.33', ':1.11', 'org.kde.kwin.Screenshot', ':1.56', ':1.34', 'org.kde.StatusNotifierWatcher', 'org.kde.JobViewServer', ':1.35', ':1.0', ':1.13', ':1.58', 'org.kde.StatusNotifierHost-616', ':1.14', ':1.59', ':1.15', ':1.38', ':1.16', 'org.kde.ksmserver', ':1.39', ':1.17', ':1.5', 'org.kde.Solid.PowerManagement.PolicyAgent', ':1.18', 'org.kde.klauncher', ':1.6', ':1.19'] }}} The following example makes your system hibernate: {{{ # Get the power management object power = bus.get('org.gnome.PowerManager', '/org/gnome/PowerManager') # Hibernate the system if power.CanHibernate(): power.Hibernate() |
Line 73: | Line 78: |
Notice that the exception is triggered in the `.Introspect()` call, not in the erroneous `bus.get_object()` call. | = dasbus = For more information see [[https://dasbus.readthedocs.io/|dasbus's documentation]]. |
Line 75: | Line 81: |
= Calling an interface method = | == Introspection of a remote object == |
Line 77: | Line 83: |
After executing the introspection example: | Introspection returns an XML string containing information about interfaces, methods, properties and signals of the remote object. |
Line 79: | Line 86: |
# Get a particular interface iface = dbus.Interface(remote_object, 'org.freedesktop.DBus') print iface.ListNames() |
from dasbus.connection import SessionMessageBus bus = SessionMessageBus() # Create an object that will be a proxy for a particular remote object. remote_object = bus.get_proxy( "org.freedesktop.DBus", # The bus name "/org/freedesktop/DBus" # The object path ) # Call the Introspect method of the remote object. print(remote_object.Introspect()) |
Line 84: | Line 99: |
Output: | == Accessing a remote property == The following example prints the current hostname. |
Line 86: | Line 104: |
[u'org.freedesktop.DBus', u':1.3', u'org.freedesktop.Notifications', u'org.gnome.PowerManager', u':1.24', u':1.4', u':1.0', u'org.gnome.ScreenSaver', u':1.5', u':1.1', u':1.48', u':1.2'] | from dasbus.connection import SystemMessageBus bus = SystemMessageBus() |
Line 88: | Line 107: |
proxy = bus.get_proxy( "org.freedesktop.hostname1", "/org/freedesktop/hostname1" ) print(proxy.Hostname) |
|
Line 90: | Line 115: |
== Calling a remote method == | |
Line 91: | Line 117: |
The following example makes your system hibernate: | The following example sends a notification to the notification server. |
Line 93: | Line 120: |
# Get the power management object power = bus.get_object('org.gnome.PowerManager', '/org/gnome/PowerManager') iface = dbus.Interface(power, 'org.gnome.PowerManager') |
from dasbus.connection import SessionMessageBus bus = SessionMessageBus() |
Line 98: | Line 123: |
# Hibernate the system if iface.CanHibernate(): iface.Hibernate() |
proxy = bus.get_proxy( "org.freedesktop.Notifications", "/org/freedesktop/Notifications" ) id = proxy.Notify( "", 0, "face-smile", "My notification", "Hello World!", [], {}, 0 ) print("The notification {} was sent.".format(id)) |
The D-Bus library is a messaging library used by various desktop environments (GNOME, KDE, etc) for interprocess communication.
There are multiple Python bindings for DBus:
GDbus and QtDbus are wrappers over the C/C++ APIs of GLib and Qt
pydbus is a modern, pythonic API with the goal of being as invisible a layer between the exported API and its user as possible
dasbus is a Python3-only alternative to pydbus with additional features and better flexibility
dbus-python is a legacy API, built with a deprecated dbus-glib library, and involving a lot of type-guessing (despite "explicit is better than implicit" and "resist the temptation to guess").
txdbus is a native Python implementation of the D-Bus protocol for the Twisted networking framework.
See also: DBusBindings on Freedesktop wiki.
The dbus-viewer and qdbusviewer programs let you browse through the services and interfaces available on your system.
pydbus
For more information see pydbus's Readme.
Introspection
from pydbus import SessionBus bus = SessionBus() # Create an object that will proxy for a particular remote object. remote_object = bus.get( "org.freedesktop.DBus", # Bus name "/org/freedesktop/DBus" # Object path ) # Introspection returns an XML document containing information # about the methods supported by an interface. print ("Introspection data:\n") print (remote_object.Introspect()[0])
Output:
Introspection data: <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg name="data" direction="out" type="s"/> </method> </interface> <interface name="org.freedesktop.DBus"> <method name="RequestName"> <arg direction="in" type="s"/> <arg direction="in" type="u"/> <arg direction="out" type="u"/> </method> ...
Calling an interface method
After executing the introspection example:
print(remote_object.ListNames()[0])
Output:
['org.freedesktop.DBus', 'org.freedesktop.Notifications', 'org.freedesktop.PowerManagement', ':1.8', ':1.9', 'org.kde.kaccess', 'org.kde.kded', 'org.kde.StatusNotifierItem-655-1', 'org.freedesktop.systemd1', 'org.ktorrent.ktorrent', 'org.kde.StatusNotifierItem-656-1', 'org.kde.konversation', 'org.pulseaudio.Server', 'org.kde.KScreen', 'org.kde.krunner', 'org.kde.konsole', ':1.40', 'org.a11y.Bus', ':1.41', ':1.42', ':1.20', ':1.43', 'org.kde.klauncher5', ':1.21', ':1.23', 'org.kde.dolphin-3012', 'org.freedesktop.PowerManagement.Inhibit', 'org.kde.Solid.PowerManagement', ':1.24', ':1.25', ':1.49', 'org.kde.kmix', 'org.kde.screensaver', 'org.kde.KWin', 'org.bluez.obex', ':1.29', 'ca.desrt.dconf', 'org.kde.kgpg', 'org.freedesktop.ScreenSaver', 'org.kde.plasmashell', 'org.kde.plasmanetworkmanagement', 'org.kde.StatusNotifierItem-666-1', 'org.kde.kglobalaccel', 'org.freedesktop.FileManager1', 'org.kde.kwalletd5', 'org.PulseAudio1', 'org.kde.polkit-kde-authentication-agent-1', ':1.93', 'org.kde.kded5', 'org.kde.ActivityManager', 'org.kde.keyboard', 'org.kde.kate-3030', ':1.31', 'org.kde.kuiserver', ':1.32', ':1.55', ':1.33', ':1.11', 'org.kde.kwin.Screenshot', ':1.56', ':1.34', 'org.kde.StatusNotifierWatcher', 'org.kde.JobViewServer', ':1.35', ':1.0', ':1.13', ':1.58', 'org.kde.StatusNotifierHost-616', ':1.14', ':1.59', ':1.15', ':1.38', ':1.16', 'org.kde.ksmserver', ':1.39', ':1.17', ':1.5', 'org.kde.Solid.PowerManagement.PolicyAgent', ':1.18', 'org.kde.klauncher', ':1.6', ':1.19']
The following example makes your system hibernate:
# Get the power management object power = bus.get('org.gnome.PowerManager', '/org/gnome/PowerManager') # Hibernate the system if power.CanHibernate(): power.Hibernate()
dasbus
For more information see dasbus's documentation.
Introspection of a remote object
Introspection returns an XML string containing information about interfaces, methods, properties and signals of the remote object.
from dasbus.connection import SessionMessageBus bus = SessionMessageBus() # Create an object that will be a proxy for a particular remote object. remote_object = bus.get_proxy( "org.freedesktop.DBus", # The bus name "/org/freedesktop/DBus" # The object path ) # Call the Introspect method of the remote object. print(remote_object.Introspect())
Accessing a remote property
The following example prints the current hostname.
from dasbus.connection import SystemMessageBus bus = SystemMessageBus() proxy = bus.get_proxy( "org.freedesktop.hostname1", "/org/freedesktop/hostname1" ) print(proxy.Hostname)
Calling a remote method
The following example sends a notification to the notification server.
from dasbus.connection import SessionMessageBus bus = SessionMessageBus() proxy = bus.get_proxy( "org.freedesktop.Notifications", "/org/freedesktop/Notifications" ) id = proxy.Notify( "", 0, "face-smile", "My notification", "Hello World!", [], {}, 0 ) print("The notification {} was sent.".format(id))