Wie liste ich alle Objektpfade unter einem dbus-Dienst auf?


16

Dies ist eine Folgefrage zu Eine Liste der verfügbaren DBus-Dienste .

Der folgende Python-Code listet alle verfügbaren DBus-Dienste auf.

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

Wie listen wir die Objektpfade unter den Diensten in Python auf? Es ist in Ordnung, wenn die Antwort kein Python enthält, obwohl dies bevorzugt wird.

Ich benutze Ubuntu 14.04


Es ist in Ordnung, wenn die Antwort kein Python enthält, obwohl dies bevorzugt wird.
user768421

Antworten:


15

Gemäß den offiziellen Dokumenten (unter Standardschnittstellen ):

Es gibt einige Standardschnittstellen, die für verschiedene D-Bus-Anwendungen nützlich sein können.

org.freedesktop.DBus.Introspectable

Diese Schnittstelle hat eine Methode:

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

Es können Objektinstanzen implementiert werden, Introspectdie eine XML- Beschreibung des Objekts, einschließlich seiner Schnittstellen (mit Signalen und Methoden), darunter liegender Objekte in der Objektpfadstruktur und seiner Eigenschaften, zurückgeben.

Hier ist ein sehr vereinfachtes Beispiel, das Ihnen den Einstieg erleichtern soll. Es verwendet xml.etree.ElementTreeund 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')

Es prüft rekursiv org.freedesktop.UPowerab zB /org/freedesktop/UPowerund gibt alle Objektpfade (Knotennamen) aus:

/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

Das ist so ziemlich das, was Sie bekommen würden, wenn Sie es benutzen würden d-feet(nicht, dass Sie es brauchen würden):

Bildbeschreibung hier eingeben


Natürlich können Sie die Objektpfade einfach über die Befehlszeile abrufen, z. B . gdbus:

gdbus introspect --system --dest org.freedesktop.UPower --objektpfad \
/ 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

Ich habe qdbusaber laut dieser Seite nicht installiert

qdbus --system org.freedesktop.UPower

sollte ein ähnliches Ergebnis erzeugen.


Wie erstelle ich eine Liste von Objektpfaden rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')?
Khurshid Alam

Nein, ich meine das Erstellen einer Python-Liste von Objektpfaden, damit ich (in meinem Skript) überprüfen kann, ob ein bestimmter Objektpfad in der Liste vorhanden ist. Es druckt den Objektpfad in Ordnung., Aber ich möchte so etwas k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower'). Ich nehme an, es ist möglich, indem man die Funktion ein wenig ändert.
Khurshid Alam

Beispielcode mit 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 - initialisiere eine Liste vor der Funktion, z. B. mylist=[]dann ersetze sie printdurch mylist.appendund dann als letzten Befehl in diesem Funktionsblock return mylist- das ist so ziemlich das, was es gibt ... dann kannst du die Liste durchlaufen oder was auch immer, z. B. am Ende des Skripts hinzufügen for x in mylist: print("OBJ_PATH", x)um sie mit einem OBJ_PATHPräfix drucken zu lassen ...
don_crissti

4

Ich bin nicht sicher, ob Sie dies programmgesteuert in Python tun können. Sie könnten, aber es wird ein riesiger Kopfschmerz sein, um herauszufinden, wie. Ich habe es schon früher versucht und am Ende Dbus gehasst. Jedenfalls empfehle ich die Verwendung von D-Füßen, wenn Sie Dinge untersuchen möchten. Unten ist ein Screenshot, den ich aus meinem Blog gestohlen habe .

Bildbeschreibung hier eingeben

Sobald Sie den Programmnamen, den Objektpfad usw. kennen, können Sie mit Python auf diese Dinge zugreifen.

Beispiel

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

Wie Sie sehen, ist es eine Qual, eine einfache Sache zu erledigen. Dies ist jedoch der einfachste Workflow, den Sie mit Dbus erhalten können!

Verwenden Sie also ein GUI-Tool, um die Objektpfade, Schnittstellen usw. herauszufinden. Verwenden Sie dann den obigen Codeausschnitt als Vorlage, um auf diese Dinge zuzugreifen. Außerdem empfehle ich Ihnen, dies über den IPython-Interpreter zu tun, um zu sehen, welche Methoden, Eigenschaften usw. jedes Objekt hat (indem Sie auf die Registerkarte klicken).



1

Was ich aus meiner Erfahrung weiß, um die Objektpfade eines Busnamens (Dienstes) zu erhalten, ist es möglich, den Objektpfad '/' (anhand des obigen Beispiels) zu überprüfen.

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

dies sollte zurückgeben:

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

dann Introspektion mit Pfad '/ org'

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

dies sollte zurückgeben:

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

und so weiter:

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

Es ist so, als würde man die Ordnerstruktur der Festplatte durchgehen, wobei der Objektpfad '/' der Stamm ist und jeder Knoten ein Unterordner ist. Dies scheint der beste Weg zu sein, um die Objektpfade eines bestimmten Busnamens (Dienstes) abzurufen und eine Sammlung mit den Objektpfaden zu erstellen


1

Wie pro #don_crissti Antworten, ich implementiert, gibt diese Lösung zu Schnittstellennamen und Verfahren und Signale Informationen

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.