Как перечислить все пути к объектам в службе dbus?

16

Это дополнительный вопрос к списку доступных сервисов DBus .

В следующем коде Python перечислены все доступные службы DBus.

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

Как мы перечисляем пути к объектам в службах в Python? Это нормально, если ответ не включает в себя Python, хотя это предпочтительнее.

Я использую Ubuntu 14.04

user768421
источник
Это нормально, если ответ не включает в себя Python, хотя это предпочтительнее.
user768421

Ответы:

15

Согласно официальным документам (под стандартными интерфейсами ):

Есть несколько стандартных интерфейсов, которые могут быть полезны для различных приложений 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начиная, например, /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}'
/ Орг / Freedesktop / UPower
/ Орг / Freedesktop / UPower / пробуждения
/ орг / Freedesktop / UPower / устройства
/ Орг / Freedesktop / UPower / устройства / DisplayDevice
/ Орг / Freedesktop / UPower / устройства / battery_BAT0
/ Орг / Freedesktop / UPower / устройства / line_power_ADP0

Я не qdbusустановил, но в соответствии с этой страницей

qdbus --system org.freedesktop.UPower

должен дать аналогичный результат.

don_crissti
источник
Как мне создать список путей к объектам rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')?
Хуршид Алам
Нет, я имею в виду создание списка путей к объектам в python, чтобы я мог проверить (в моем скрипте), существует ли конкретный путь к объекту в списке. Он печатает путь объекта в порядке., Но я хочу что-то вроде k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower'). Я полагаю, это возможно, немного изменив функцию.
Хуршид Алам
Пример кода с 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
Хуршид Алам
@KhurshidAlam - инициализируйте список перед функцией, например, mylist=[]затем замените printна mylist.appendи затем в качестве последней команды в этом функциональном блоке return mylist- это почти то, что есть ... затем вы можете выполнить итерации по списку или что угодно, например, добавить внизу скрипта for x in mylist: print("OBJ_PATH", x)чтобы они были напечатаны с OBJ_PATHпрефиксом ...
don_crissti
4

Я не уверен, что вы можете сделать это программно в Python. Вы могли бы, но это будет огромная головная боль, чтобы выяснить, как. Я пытался сделать это раньше и закончил ненавидеть Dbus. Во всяком случае, я рекомендую использовать D-ноги, если вы хотите исследовать вещи. Ниже приведен скриншот, который я украл из своего блога .

введите описание изображения здесь

Когда вы знаете имя программы, путь к объекту и т. Д., Вы можете использовать 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!

Поэтому используйте инструмент с графическим интерфейсом, чтобы узнать пути к объектам, интерфейсы и т. Д. Затем используйте приведенный выше фрагмент кода в качестве шаблона для доступа к этим вещам. Также я предлагаю вам сделать это через интерпретатор IPython, чтобы увидеть, какие методы, свойства и т. Д. У каждого объекта (нажав на вкладку).

Pithikos
источник
1

То, что я знаю из своего опыта, чтобы получить пути к объектам имени шины (службы), можно проанализировать с помощью пути к объекту '/', т. Е. (Используя приведенный выше пример)

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.

Это похоже на просмотр структуры папок жесткого диска, где путь к объекту '/' является корневым, а каждый узел - подпапкой. Это кажется наилучшим способом получения путей к объектам определенного имени шины (службы) и создания коллекции, содержащей пути к объектам.

qnbibiqn
источник
1

В соответствии с #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)
Рейган Миранда
источник