如何列出dbus服务下的所有对象路径?


16

这是“可用的DBus服务列表”的后续问题。

以下python代码将列出所有可用的DBus服务。

import dbus
for service in dbus.SystemBus().list_names():
    print(service)

我们如何列出python服务中的对象路径?可以选择,但答案不涉及python也可以。

我正在使用Ubuntu 14.04


可以选择,但答案不涉及python也可以。
user768421

Answers:


15

根据官方文档(在标准界面下):

有些标准接口可能在各种D-Bus应用程序中有用。

org.freedesktop.DBus.Introspectable

此接口有一种方法:

org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)

对象实例可以实现Introspect,该对象实例返回对象的XML 描述,包括其接口(带有信号和方法),对象路径树中位于其下方的对象及其属性。

因此,这是一个非常简单的示例,应该可以帮助您入门。它使用xml.etree.ElementTreedbus

#!/usr/bin/env python

import dbus
from xml.etree import ElementTree

def rec_intro(bus, service, object_path):
    print(object_path)
    obj = bus.get_object(service, object_path)
    iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
    xml_string = iface.Introspect()
    for child in ElementTree.fromstring(xml_string):
        if child.tag == 'node':
            if object_path == '/':
                object_path = ''
            new_path = '/'.join((object_path, child.attrib['name']))
            rec_intro(bus, service, new_path)

bus = dbus.SystemBus()
rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')

org.freedesktop.UPower从eg开始递归内省,/org/freedesktop/UPower并打印所有对象路径(节点名称):

/org/freedesktop/UPower
/org/freedesktop/UPower/Wakeups
/org/freedesktop/UPower/devices
/org/freedesktop/UPower/devices/DisplayDevice
/org/freedesktop/UPower/devices/battery_BAT0
/org/freedesktop/UPower/devices/line_power_ADP0

如果您使用过,这几乎就是您会得到的d-feet(不是您需要它):

在此处输入图片说明


当然,您可以通过命令行轻松获得对象路径,例如gdbus

gdbus内省--system --dest org.freedesktop.UPower --object-path \
/ org / freedesktop / UPower --recurse | awk'/ ^ * node / {print $ 2}'
/ org / freedesktop / UPower
/ org / freedesktop / UPower /唤醒
/ org / freedesktop / UPower / devices
/ org / freedesktop / UPower / devices / DisplayDevice
/ org / freedesktop / UPower / devices / battery_BAT0
/ org / freedesktop / UPower / devices / line_power_ADP0

我尚未qdbus安装,但根据此页面

qdbus --system org.freedesktop.UPower

应该会产生类似的结果。


如何创建来自的对象路径列表rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')
库尔希德·阿拉姆

不,我的意思是创建对象路径的python列表,以便可以检查(在我的脚本中)列表中是否存在特定的对象路径。它可以打印出对象路径。,但是我想要类似的东西k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')。我想可以通过稍微修改一下功能来实现。
库尔希德·阿拉姆

qbus的示例代码:bus = dbus.SessionBus()..... obj_path = '/org/gnome/Gnote/RemoteControl'.......... cmd = 'qdbus org.gnome.Gnote'......... while obj_path not in ((subprocess.check_output(cmd, shell=True)).decode("utf-8")).split("\n"): ........pass
Khurshid Alam

@KhurshidAlam-在函数之前初始化一个列表,例如,mylist=[]然后替换printmylist.append,然后作为该功能块中的最后一个命令return mylist-这几乎是什么...您可以在列表上进行迭代,或者诸如此类,在脚本底部添加for x in mylist: print("OBJ_PATH", x)让它们印有OBJ_PATH前缀...
don_crissti 17-4-28

4

我不确定您可以使用Python以编程方式执行此操作。您可能会发现,但要弄清楚该如何做将是一个巨大的头痛。我曾经尝试过这样做,最终讨厌Dbus。无论如何,我建议您使用d-feet进行调查。以下是我从博客中窃取的屏幕截图。

在此处输入图片说明

一旦知道了程序名称,对象路径等,就可以使用Python来访问这些内容。

progname = 'org.freedesktop.NetworkManager'
objpath  = '/org/freedesktop/NetworkManager'
intfname = 'org.freedesktop.NetworkManager'
methname = 'GetDevices'

bus = dbus.SystemBus()

obj  = bus.get_object(progname, objpath)  # Here we get object
intf = dbus.Interface(obj, intfname)      # Here we get interface
meth = inf.get_dbus_method(methname)      # Here we get method

meth()                                    # And finally calling the method

如您所见,完成一件简单的事情真是费劲。但这是Dbus可以提供的最简单的工作流程!

因此,请使用GUI工具找出对象路径,接口等。然后使用上面的代码段作为模板来访问这些内容。我也建议您通过IPython的解释器执行此操作,以查看每个对象具有哪些方法,属性等(通过单击选项卡)。



1

根据我的经验,知道要获取总线名称(服务)的对象路径,可以对对象路径“ /”进行自省,即(使用上面的示例)

introspectfunc('org.freedesktop.UPower', '/') 

这应该返回:

<node name="/"> 
<node name="org"/>
<node name="org"/>
<node name="org"/>
<node name="org"/>
<node name="org"/>
<node name="org"/></node>

然后使用路径'/ org'进行内省

introspectfunc('org.freedesktop.UPower', '/org')

这应该返回:

<node name="/org"> 
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/>
<node name="freedesktop"/></node>

等等:

introspectfunc('org.freedesktop.UPower', '/org/freedesktop')
introspectfunc('org.freedesktop.UPower', '/org/freedesktop/UPower')
etc.

就像遍历硬盘驱动器的文件夹结构一样,其中对象路径“ /”是根目录,每个节点都是子文件夹。这似乎是检索特定总线名称(服务)的对象路径并构造包含对象路径的集合的最佳方法。


1

按照#don_crissti的答案,我实现了,此解决方案提供接口名称和方法,并发出信号信息

import dbus
from xml.etree import ElementTree
bus = dbus.SystemBus()

def busNames():
    return [ name for name in  bus.list_names() if not name.startswith(":") ]


def pathNames(service,object_path="/",paths=None,serviceDict=None):
    if paths == None:
        paths = {}
    paths[object_path] = {}
    obj = bus.get_object(service, object_path)
    iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
    xml_string = iface.Introspect()
    root = ElementTree.fromstring(xml_string)
    for child in root:
        if child.tag == 'node':
            if object_path == '/':
                    object_path = ''
            new_path = '/'.join((object_path, child.attrib['name']))
            pathNames(service, new_path,paths)
        else:
            if object_path == "":
                object_path = "/"
            functiondict = {}
            paths[object_path][child.attrib["name"]] = functiondict
            for func in child.getchildren():
                if func.tag not in functiondict.keys():
                    functiondict[func.tag] =[]
                functiondict[func.tag].append(func.attrib["name"])
    if serviceDict == None:
        serviceDict = {}
    serviceDict[service] = paths
    return serviceDict



import json
import random
service=random.sample(busNames(),1).pop()
print service
print json.dumps(pathNames(service),indent=3)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.