You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python 3中从dbus迁移至GDBus:寻求Python版GDBus服务示例

Python GDBus Service Example for Your Existing D-Bus Workflow

Hey Dominik, I totally get it—scouring for Python GDBus examples when most resources are C-focused is frustrating. Since you already have experience building D-Bus services, switching to GDBus using Python's Gio bindings should click once you see a working example tailored to your needs. Below is a complete, tested service that includes methods, properties, and signals—core pieces you’ll need for most GDBus work.

Full Working Example

First, make sure you have the python3-gi package installed (on Debian/Ubuntu: sudo apt install python3-gi). This gives you access to the Gio bindings for GDBus.

import gi
gi.require_version('Gio', '2.0')
from gi.repository import Gio, GLib

# Define your GDBus interface using XML (matches C-style IDL)
INTERFACE_XML = """
<node>
  <interface name="com.example.MyGDBusService">
    <!-- A simple method that takes a string and returns a greeting -->
    <method name="Hello">
      <arg type="s" name="username" direction="in"/>
      <arg type="s" name="greeting" direction="out"/>
    </method>
    <!-- A read-write integer property -->
    <property name="RequestCount" type="u" access="readwrite"/>
    <!-- A signal emitted when the property changes -->
    <signal name="RequestCountUpdated">
      <arg type="u" name="new_count"/>
    </signal>
  </interface>
</node>
"""

class GDBusService(Gio.Application):
    def __init__(self):
        # Use a unique application ID (follows reverse domain notation)
        super().__init__(
            application_id="com.example.MyGDBusService",
            flags=Gio.ApplicationFlags.FLAGS_NONE
        )
        self.request_count = 0

    def do_activate(self):
        """Called when the application is activated (starts the service)"""
        # Get the D-Bus connection tied to our application
        dbus_connection = self.get_dbus_connection()
        
        # Register our GDBus object with the connection
        self.registration_id = dbus_connection.register_object(
            object_path="/com/example/MyGDBusService",
            interface_info=Gio.DBusNodeInfo.new_for_xml(INTERFACE_XML).lookup_interface("com.example.MyGDBusService"),
            method_call_closure=self._handle_method_calls,
            get_property_closure=self._handle_get_property,
            set_property_closure=self._handle_set_property,
            user_data=None
        )
        print("GDBus service running. Use gdbus to interact with it!")

    def _handle_method_calls(self, connection, sender, object_path, interface_name, method_name, parameters, invocation):
        """Handle incoming method calls from clients"""
        if method_name == "Hello":
            username = parameters[0]
            self.request_count += 1
            # Emit the signal to notify clients of the count change
            connection.emit_signal(
                None,  # No specific destination (broadcast)
                "/com/example/MyGDBusService",
                "com.example.MyGDBusService",
                "RequestCountUpdated",
                GLib.Variant("(u)", (self.request_count,))
            )
            # Return the greeting to the caller
            invocation.return_value(GLib.Variant("(s)", (f"Hello {username}! You've made {self.request_count} requests.",)))
        else:
            invocation.return_error_literal(Gio.dbus_error_quark(), Gio.DBusError.UNKNOWN_METHOD, f"Method {method_name} not found")

    def _handle_get_property(self, connection, sender, object_path, interface_name, property_name):
        """Handle property read requests"""
        if property_name == "RequestCount":
            return GLib.Variant("u", self.request_count)
        raise GLib.Error(f"Unknown property: {property_name}")

    def _handle_set_property(self, connection, sender, object_path, interface_name, property_name, value):
        """Handle property write requests"""
        if property_name == "RequestCount":
            old_count = self.request_count
            self.request_count = value.get_uint32()
            if old_count != self.request_count:
                # Emit signal if the count changed
                connection.emit_signal(
                    None,
                    "/com/example/MyGDBusService",
                    "com.example.MyGDBusService",
                    "RequestCountUpdated",
                    GLib.Variant("(u)", (self.request_count,))
                )
        else:
            raise GLib.Error(f"Unknown property: {property_name}")

if __name__ == "__main__":
    app = GDBusService()
    app.run(None)

How to Test the Service

  1. Run the script: python3 gdbus_service.py
  2. In a separate terminal, test the method:
    gdbus call --session --dest com.example.MyGDBusService --object-path /com/example/MyGDBusService --method com.example.MyGDBusService.Hello "Dominik"
    
  3. Check the property value:
    gdbus get --session --dest com.example.MyGDBusService --object-path /com/example/MyGDBusService --property com.example.MyGDBusService.RequestCount
    
  4. Monitor for the signal (run this in another terminal):
    gdbus monitor --session --dest com.example.MyGDBusService
    
    Then set the property to trigger the signal:
    gdbus set --session --dest com.example.MyGDBusService --object-path /com/example/MyGDBusService --property com.example.MyGDBusService.RequestCount 10
    

Key Notes for Your Workflow

  • Interface XML: This is the same IDL format used in C GDBus code, so you can reuse or adapt existing interface definitions you might have.
  • Application Integration: Since this uses Gio.Application, it plays nicely with other GLib-based tools and handles D-Bus registration cleanly (no need for manual bus connection setup).
  • System Bus vs Session Bus: If you need to run this on the system bus instead of the session bus, you’ll need to add a policy file in /usr/share/dbus-1/system.d/ to grant permissions for your service ID and object path.

This example covers the core GDBus features you’ll likely need, and you can extend it with more methods, properties, or signals as your project requires.

内容的提问来源于stack exchange,提问作者Dominik Möslinger

火山引擎 最新活动