这是“可用的DBus服务列表”的后续问题。
以下python代码将列出所有可用的DBus服务。
import dbus
for service in dbus.SystemBus().list_names():
print(service)
我们如何列出python服务中的对象路径?可以选择,但答案不涉及python也可以。
我正在使用Ubuntu 14.04
这是“可用的DBus服务列表”的后续问题。
以下python代码将列出所有可用的DBus服务。
import dbus
for service in dbus.SystemBus().list_names():
print(service)
我们如何列出python服务中的对象路径?可以选择,但答案不涉及python也可以。
我正在使用Ubuntu 14.04
Answers:
根据官方文档(在标准界面下):
有些标准接口可能在各种D-Bus应用程序中有用。
org.freedesktop.DBus.Introspectable
此接口有一种方法:
org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)
对象实例可以实现
Introspect
,该对象实例返回对象的XML 描述,包括其接口(带有信号和方法),对象路径树中位于其下方的对象及其属性。
因此,这是一个非常简单的示例,应该可以帮助您入门。它使用xml.etree.ElementTree
和dbus
:
#!/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')
?
k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')
。我想可以通过稍微修改一下功能来实现。
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
mylist=[]
然后替换print
为mylist.append
,然后作为该功能块中的最后一个命令return mylist
-这几乎是什么...您可以在列表上进行迭代,或者诸如此类,在脚本底部添加for x in mylist: print("OBJ_PATH", x)
让它们印有OBJ_PATH
前缀...
我不确定您可以使用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的解释器执行此操作,以查看每个对象具有哪些方法,属性等(通过单击选项卡)。
如果服务具有实现的对象org.freedesktop.DBus.ObjectManager
,则其方法GetManagedObjects
将返回“单个方法调用中的所有对象,接口和属性”。例如,UDisks2具有此类对象。
根据我的经验,知道要获取总线名称(服务)的对象路径,可以对对象路径“ /”进行自省,即(使用上面的示例)
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.
就像遍历硬盘驱动器的文件夹结构一样,其中对象路径“ /”是根目录,每个节点都是子文件夹。这似乎是检索特定总线名称(服务)的对象路径并构造包含对象路径的集合的最佳方法。
按照#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)