Features:
- Asyncio and blocking calls.
- Type hints. (
mypy --strictcompatible) - No Python 2 legacy.
- Based on fast sd-bus from systemd. (also supports elogind)
- Unified client/server interface classes. Write interface once!
- D-Bus methods can have keyword and default arguments.
See the documentation for tutorial and API reference.
- D-Bus (built-in)
- Freedesktop Notifications
- Network Manager
- Freedesktop Secrets
More incoming. (systemd, Bluez, screen saver... )
- systemd (by @bernhardkaindl)
- modemmanager (by @zhanglongqi)
Python-sdbus is under development and its API is not stable. Generally anything documented in the official documentation is considered stable but might be deprecated. Using deprecated feature will raise a warning and the feature will be eventually removed.
See the deprecations list.
If there is a feature that is not documented but you would like to use please open a new issue.
- Python 3.9 or higher.
x86_64,aarch64orarmv7larchitecture.- glibc 2.28 or higher. (Debian 10+, Ubuntu 18.10+, CentOS/RHEL 8+)
- pip 20.3 or higher.
libsystemd is statically linked and is not required to be installed
on the system.
Pass --only-binary ':all:' to pip to ensure that it
installs binary package.
i686, ppc64le and s390x can be supported if there is a
demand. Please open an issue if you are interested in those
platforms.
- Python 3.9 or higher.
- Python headers. (
python3-devpackage on ubuntu) - GCC.
- libsystemd or libelogind
- libsystemd headers. (
libsystemd-devpackage on ubuntu) - Python setuptools.
- pkg-config
Systemd version should be higher than 246.
- Jinja2 for code generator.
- Sphinx for autodoc.
URL: https://pypi.org/project/sdbus/
pip install --only-binary ':all:' sdbus
URL: https://aur.archlinux.org/packages/python-sdbus-git/
Interface example_interface.py file:
fromsdbusimport (DbusInterfaceCommonAsync, dbus_method_async,
dbus_property_async, dbus_signal_async)
# This is file only contains interface definition for easy import# in server and client filesclassExampleInterface(
DbusInterfaceCommonAsync,
interface_name='org.example.interface'
):
@dbus_method_async(input_signature='s',result_signature='s', )asyncdefupper(self, string: str) ->str:
returnstring.upper()
@dbus_property_async(property_signature='s', )defhello_world(self) ->str:
return'Hello, World!'@dbus_signal_async(signal_signature='i' )defclock(self) ->int:
raiseNotImplementedErrorServer example_server.py file:
fromasyncioimportnew_event_loop, sleepfromrandomimportrandintfromtimeimporttimefromexample_interfaceimportExampleInterfacefromsdbusimportrequest_default_bus_name_asyncloop=new_event_loop()
export_object=ExampleInterface()
asyncdefclock() ->None:
""" This coroutine will sleep a random time and emit a signal with current clock """whileTrue:
awaitsleep(randint(2, 7)) # Sleep a random timecurrent_time=int(time()) # The interface we defined uses integersexport_object.clock.emit(current_time)
asyncdefstartup() ->None:
"""Perform async startup actions"""# Acquire a known name on the bus# Clients will use that name to address this serverawaitrequest_default_bus_name_async('org.example.test')
# Export the object to D-Busexport_object.export_to_dbus('/')
loop.run_until_complete(startup())
task_clock=loop.create_task(clock())
loop.run_forever()Client example_client.py file:
fromasyncioimportnew_event_loopfromexample_interfaceimportExampleInterface# Create a new proxied objectexample_object=ExampleInterface.new_proxy('org.example.test', '/')
asyncdefprint_clock() ->None:
# Use async for loop to print clock signals we receiveasyncforxinexample_object.clock:
print('Got clock: ', x)
asyncdefcall_upper() ->None:
s='test string's_after=awaitexample_object.upper(s)
print('Initial string: ', s)
print('After call: ', s_after)
asyncdefget_hello_world() ->None:
print('Remote property: ', awaitexample_object.hello_world)
loop=new_event_loop()
# Always bind your tasks to a variabletask_upper=loop.create_task(call_upper())
task_clock=loop.create_task(print_clock())
task_hello_world=loop.create_task(get_hello_world())
loop.run_forever()Python-sdbus is licensed under LGPL-2.1-or-later.
The LGPL license is an extension of GPL license therefore both licenses' texts are required.