Comment répertorier tous les chemins d'objet sous un service dbus?

16

Il s'agit d'une question complémentaire à Une liste des services DBus disponibles .

Le code python suivant répertorie tous les services DBus disponibles.

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

Comment répertorier les chemins d'objet sous les services en python? C'est correct si la réponse n'implique pas python bien que cela soit préféré.

J'utilise Ubuntu 14.04

user768421
la source
C'est correct si la réponse n'implique pas python bien que cela soit préféré.
user768421

Réponses:

15

Selon les documents officiels (sous les interfaces standard ):

Il existe certaines interfaces standard qui peuvent être utiles dans diverses applications D-Bus.

org.freedesktop.DBus.Introspectable

Cette interface a une méthode:

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

Les instances d'objets peuvent implémenter Introspectqui renvoie une description XML de l'objet, y compris ses interfaces (avec des signaux et des méthodes), les objets situés en dessous dans l'arborescence du chemin d'objet et ses propriétés.

Voici donc un exemple très simpliste qui devrait vous aider à démarrer. Il utilise xml.etree.ElementTreeet 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')

Il introspecte récursivement à org.freedesktop.UPowerpartir de par exemple/org/freedesktop/UPower et imprime tous les chemins d'objet (noms de noeud):

/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

ce qui est à peu près ce que vous obtiendriez si vous l'utilisiez d-feet(pas que vous en auriez besoin):

entrez la description de l'image ici


Bien sûr, vous pouvez facilement obtenir les chemins des objets via la ligne de commande, par exemple avec 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 / appareils
/ org / freedesktop / UPower / devices / DisplayDevice
/ org / freedesktop / UPower / devices / battery_BAT0
/ org / freedesktop / UPower / devices / line_power_ADP0

Je n'ai pas qdbusinstallé mais selon cette page

qdbus --system org.freedesktop.UPower

devrait produire un résultat similaire.

don_crissti
la source
Comment créer une liste de chemins d'objets à partir de rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')?
Khurshid Alam
Non, je veux dire créer une liste python de chemins d'objets, afin que je puisse vérifier (dans mon script) si un chemin objet particulier existe dans la liste. Il imprime bien le chemin d'objet., Mais je veux quelque chose comme k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower'). Je suppose que c'est possible en modifiant un peu la fonction.
Khurshid Alam
Exemple de code avec 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 - initialiser une liste avant la fonction, par exemple, mylist=[]puis remplacer printpar mylist.appendet ensuite comme dernière commande dans ce bloc de fonction return mylist- c'est à peu près ce qu'il y a ... vous pouvez ensuite parcourir la liste ou quoi que ce soit, par exemple, ajouter au bas du script for x in mylist: print("OBJ_PATH", x)de les faire imprimer avec un OBJ_PATHpréfixe ...
don_crissti
4

Je ne suis pas sûr que vous puissiez le faire par programme en Python. Vous pourriez, mais ce sera un énorme casse-tête pour comprendre comment. J'ai essayé de le faire avant et j'ai fini par détester Dbus. Quoi qu'il en soit, je recommande d'utiliser des pieds en D si vous voulez enquêter sur les choses. Voici une capture d'écran que j'ai volée sur mon blog .

entrez la description de l'image ici

Une fois que vous connaissez le nom du programme, le chemin de l'objet, etc., vous pouvez alors utiliser Python pour accéder à ces choses.

Exemple

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

Comme vous le voyez, c'est difficile de faire une chose simple. Mais c'est le flux de travail le plus simple que vous puissiez obtenir avec Dbus!

Utilisez donc un outil GUI pour trouver les chemins des objets, les interfaces, etc. Utilisez ensuite l'extrait de code ci-dessus comme modèle pour accéder à ces choses. Je vous suggère également de le faire via l'interpréteur d'IPython pour voir quelles méthodes, propriétés, etc. chaque objet a (en appuyant sur tab).

Pithikos
la source
1

Ce que je sais de mon expérience pour obtenir les chemins d'objet d'un nom de bus (service), il est possible d'introspecter le chemin d'objet '/' c'est-à-dire (en utilisant l'exemple ci-dessus)

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

cela devrait retourner:

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

puis introspect avec le chemin '/ org'

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

cela devrait retourner:

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

etc:

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

C'est comme parcourir la structure de dossiers du disque dur où le chemin de l'objet '/' est la racine et chaque nœud est un sous-dossier. Cela semble être le meilleur moyen de récupérer les chemins d'objet d'un nom de bus particulier (service) et de construire une collection contenant les chemins d'objet

qnbibiqn
la source
1

Selon les réponses de #don_crissti , j'ai implémenté, Cette solution donne à l'interface le nom et la méthode et signale les informations

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)
Reegan Miranda
la source