You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dbus调用Inkscape失败(Gio方式可正常运行)

问题:使用Python dbus库调用Inkscape DBus接口报错

尝试通过DBus脚本驱动Inkscape时,基于Gio的代码可正常运行,但改用Python dbus库时出现参数不匹配的错误。

正常运行的Gio版本代码

#  Start after inkscape is running.
print("DBus test")

import gi

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

try:
   bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)

except BaseException:
   print("No DBus bus")
   exit()

print("Got DBus bus")

proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None,
                              'org.freedesktop.DBus',
                              '/org/freedesktop/DBus',
                              'org.freedesktop.DBus', None)

names_list = proxy.call_sync('ListNames', None, Gio.DBusCallFlags.NO_AUTO_START, 500, None)

# names_list is a GVariant, must unpack

names = names_list.unpack()[0]

# Look for Inkscape; names is a tuple.

for name in names:
   if ('org.inkscape.Inkscape' in name):
       print("Found: " + name)
       break

print("Name: " + name)

appGroupName = "/org/inkscape/Inkscape"
winGroupName = appGroupName + "/window/1"
docGroupName = appGroupName + "/document/1"

applicationGroup = Gio.DBusActionGroup.get( bus, name, appGroupName)
windowGroup = Gio.DBusActionGroup.get(bus, name, winGroupName)
documentGroup = Gio.DBusActionGroup.get(bus, name, docGroupName)

# Activate actions. Draw a few objects first.

applicationGroup.activate_action('select-all', GLib.Variant.new_string('all'))
applicationGroup.activate_action('object-rotate-90-cw', None)

windowGroup.activate_action('tool-switch', GLib.Variant.new_string('Arc'))
windowGroup.activate_action('canvas-zoom-page', None)

报错的dbus库版本代码

#!/usr/bin/env python

# Start after Inkscape is running.

import dbus
from xml.etree import ElementTree as ET

print("DBus test")

try:
    # Connect to the session bus
    bus = dbus.SessionBus()
except dbus.exceptions.DBusException as e:
    print(f"No DBus bus: {e}")
    exit()

print("Got DBus bus")

# Get the list of names on the bus
proxy = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
interface = dbus.Interface(proxy, 'org.freedesktop.DBus')
names = interface.ListNames()

# Look for Inkscape
name = None
for n in names:
    if 'org.inkscape.Inkscape' in n:
        name = n
        print(f"Found: {name}")
        break

if not name:
    print("Inkscape not found")
    exit()

print(f"Name: {name}")

appGroupName = "/org/inkscape/Inkscape"
winGroupName = appGroupName + "/window/1"
docGroupName = appGroupName + "/document/1"

def activate_action(group, action, parameter=None):
    try:
        group.Activate(action, parameter, dbus_interface='org.gtk.Actions')
        print(f"Activated action: {action} with parameter: {parameter}")
    except dbus.exceptions.DBusException as e:
        print(f"Failed to activate action {action}: {e}")

applicationGroup = bus.get_object(name, appGroupName)
windowGroup = bus.get_object(name, winGroupName)
documentGroup = bus.get_object(name, docGroupName)

# Activate actions. Draw a few objects first.
activate_action(applicationGroup, 'select-all', 'all')
activate_action(applicationGroup, 'object-rotate-90-cw')

报错信息

ERROR:dbus.connection:Unable to set arguments ('select-all', 'all') according to signature 'sava{sv}': <class 'TypeError'>: More items found in D-Bus signature than in Python arguments
Traceback (most recent call last):
  File "/home/simone/inkscape_experiments/dbus_05.py", line 54, in <module>
    activate_action(applicationGroup, 'select-all', 'all')
  File "/home/simone/inkscape_experiments/dbus_05.py", line 44, in activate_action
    group.Activate(action, parameter, dbus_interface='org.gtk.Actions')
  File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 72, in __call__
    return self._proxy_method(*args, **keywords)
  File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 141, in __call__
    return self._connection.call_blocking(self._named_service,
  File "/usr/lib/python3/dist-packages/dbus/connection.py", line 643, in call_blocking
    message.append(signature=signature, *args)
TypeError: More items found in D-Bus signature than in Python arguments

问题原因

错误提示中的签名sava{sv}明确了org.gtk.Actions接口的Activate方法需要3个参数:

  1. 动作名称(字符串类型,s)
  2. 参数数组(变体类型数组,av)
  3. 附加属性字典(字符串-变体键值对的字典,a{sv})

你调用时只传了2个参数,且第二个参数直接传了字符串,没有包装成变体数组,导致参数数量和类型都不匹配。

对比Gio代码,activate_action的第二个参数是GLib.Variant对象,Gio会自动将其包装成符合要求的数组;但dbus库需要手动处理参数格式。


解决方法

修改activate_action函数,按照DBus签名要求包装参数:

def activate_action(group, action, parameter=None):
    try:
        # 处理参数:有参数则包装为dbus.Variant数组,无参数则传空变体数组
        if parameter is not None:
            param_array = dbus.Array([dbus.Variant('s', parameter)], signature='v')
        else:
            param_array = dbus.Array(signature='v')
        # 附加属性传空字典
        group.Activate(action, param_array, {}, dbus_interface='org.gtk.Actions')
        print(f"Activated action: {action} with parameter: {parameter}")
    except dbus.exceptions.DBusException as e:
        print(f"Failed to activate action {action}: {e}")

查看DBus签名的方法

方法1:使用gdbus命令行工具

直接查询Inkscape的org.gtk.Actions接口信息:

gdbus introspect --session --dest org.inkscape.Inkscape --object-path /org/inkscape/Inkscape --interface org.gtk.Actions

方法2:在Python中通过Introspect接口获取

通过DBus的org.freedesktop.DBus.Introspectable接口获取XML描述,解析后查看方法签名:

# 添加到你的代码中,获取接口签名
introspect_proxy = bus.get_object(name, appGroupName)
introspect_interface = dbus.Interface(introspect_proxy, 'org.freedesktop.DBus.Introspectable')
xml_data = introspect_interface.Introspect()

root = ET.fromstring(xml_data)
for interface in root.findall('interface'):
    if interface.get('name') == 'org.gtk.Actions':
        print("org.gtk.Actions接口方法签名:")
        for method in interface.findall('method'):
            print(f"  方法名: {method.get('name')}")
            for arg in method.findall('arg'):
                print(f"    参数: {arg.get('name')} 类型: {arg.get('type')}")

内容的提问来源于stack exchange,提问作者simone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 11:52:03