これは、利用可能な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を使用しています
回答:
公式ドキュメントによると(標準インターフェイスの下):
さまざまなD-Busアプリケーションに役立つ標準インターフェイスがいくつかあります。
org.freedesktop.DBus.Introspectable
このインターフェイスには1つのメソッドがあります。
org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)
オブジェクトインスタンスは 、そのインターフェイス(信号とメソッドを含む)、オブジェクトパスツリーでその下にあるオブジェクト、およびそのプロパティを含む、オブジェクトのXML記述
Introspect
を返すように実装できます。
だから、ここにあなたが始めるべき非常に単純な例があります。以下を使用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
たとえば/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 introspect --system --dest org.freedesktop.UPower --object-path \ / org / freedesktop / UPower --recurse | awk '/ ^ * node / {print $ 2}'
/ 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
私は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
は「すべてのオブジェクト、インターフェイス、およびプロパティを1回のメソッド呼び出しで返す」を返します。たとえば、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)