Come elencare tutti i percorsi degli oggetti in un servizio dbus?


16

Questa è una domanda di follow-up a Un elenco di servizi DBus disponibili .

Il seguente codice Python elencherà tutti i servizi DBus disponibili.

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

Come elenchiamo i percorsi degli oggetti sotto i servizi in Python? Va bene se la risposta non coinvolge Python sebbene sia preferita.

Sto usando Ubuntu 14.04


Va bene se la risposta non coinvolge Python sebbene sia preferita.
user768421,

Risposte:


15

Secondo i documenti ufficiali (con interfacce standard ):

Esistono alcune interfacce standard che possono essere utili in varie applicazioni D-Bus.

org.freedesktop.DBus.Introspectable

Questa interfaccia ha un metodo:

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

Le istanze di oggetti possono implementare ciò Introspectche restituisce una descrizione XML dell'oggetto, comprese le sue interfacce (con segnali e metodi), gli oggetti sottostanti nella struttura del percorso degli oggetti e le sue proprietà.

Quindi, ecco un esempio molto semplicistico che dovrebbe iniziare. Utilizza xml.etree.ElementTreee 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')

Introspettiva ricorsiva a org.freedesktop.UPowerpartire da es. /org/freedesktop/UPowerE stampa tutti i percorsi degli oggetti (nomi dei nodi):

/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

che è praticamente quello che otterresti se lo usassi d-feet(non che ne avresti bisogno):

inserisci qui la descrizione dell'immagine


Certo, puoi facilmente ottenere i percorsi degli oggetti dalla riga di comando, ad esempio con gdbus:

gdbus introspect --system --dest org.freedesktop.UPower - percorso-oggetto \
/ org / freedesktop / UPower --recurse | awk '/ ^ * node / {print $ 2}'
/ Org / freedesktop / UPower
/ Org / freedesktop / UPower / wakeups
/ org / freedesktop / UPower / devices
/ Org / freedesktop / UPower / dispositivi / DisplayDevice
/ Org / freedesktop / UPower / dispositivi / battery_BAT0
/ Org / freedesktop / UPower / dispositivi / line_power_ADP0

Non ho qdbusinstallato ma secondo questa pagina

qdbus --system org.freedesktop.UPower

dovrebbe produrre un risultato simile.


Come faccio a creare un elenco di percorsi oggetto da rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')?
Khurshid Alam,

No, intendo creare un elenco Python di percorsi oggetto, in modo da poter verificare (nel mio script) se esiste un particolare percorso oggetto nell'elenco. Va bene il percorso dell'oggetto. Ma voglio qualcosa del genere k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower'). Suppongo che sia possibile modificando un po 'la funzione.
Khurshid Alam,

Codice di esempio con 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 - inizializza un elenco prima della funzione, ad es. mylist=[]Quindi sostituiscilo printcon mylist.appende quindi come ultimo comando in quel blocco funzione return mylist- è praticamente quello che c'è ... puoi quindi iterare sull'elenco o qualunque cosa, ad esempio, aggiungere in fondo allo script for x in mylist: print("OBJ_PATH", x)per stamparli con un OBJ_PATHprefisso ...
don_crissti,

4

Non sono sicuro che tu possa farlo programmaticamente in Python. Potresti ma sarà un grande mal di testa capire come. Ho provato a farlo prima e ho finito per odiare Dbus. Comunque ti consiglio di usare d-feet se vuoi indagare sulle cose. Di seguito è riportato uno screenshot che ho rubato dal mio blog .

inserisci qui la descrizione dell'immagine

Una volta che conosci il nome del programma, il percorso dell'oggetto, ecc., Puoi usare Python per accedere a queste cose.

Esempio

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

Come vedi, è una seccatura nel fare una cosa semplice. Ma questo è il flusso di lavoro più semplice che puoi ottenere con Dbus!

Quindi usa uno strumento GUI per scoprire i percorsi degli oggetti, le interfacce, ecc. Quindi usa lo snippet di codice sopra come modello per accedere a quelle cose. Inoltre ti suggerisco di farlo tramite l'interprete di IPython per vedere quali metodi, proprietà, ecc. Ha ogni oggetto (premendo la scheda).



1

Quello che so dalla mia esperienza per ottenere i percorsi oggetto di un nome di bus (servizio) è possibile introspettare con percorso oggetto '/' cioè (usando l'esempio sopra)

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

questo dovrebbe restituire:

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

quindi introspetto con il percorso '/ org'

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

questo dovrebbe restituire:

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

e così via:

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

È come passare attraverso la struttura delle cartelle del disco rigido in cui il percorso dell'oggetto '/' è la radice e ogni nodo è una sottocartella. Questo sembra il modo migliore per recuperare i percorsi degli oggetti di un particolare nome di bus (servizio) e costruire una raccolta contenente i percorsi degli oggetti


1

Secondo le risposte di #don_crissti , ho implementato, Questa soluzione fornisce informazioni su nome e metodo e segnali

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.