Як перелічити всі об'єктні шляхи в службі dbus?


16

Це додаткове запитання до списку доступних служб DBus .

У наведеному нижче коді python будуть перелічені всі доступні служби DBus.

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

Як ми можемо перерахувати об'єктні шляхи під службами в python? Це нормально, якщо відповідь не передбачає пітона, хоча він є кращим.

Я використовую Ubuntu 14.04


Це нормально, якщо відповідь не передбачає пітона, хоча він є кращим.
користувач768421

Відповіді:


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 --система --dest org.freedesktop.UPower --об'єкт-шлях \
/ org / freedesktop / UPower - повтор | awk '/ ^ * вузол / {print $ 2}'
/ org / freedesktop / UPower
/ org / freedesktop / UPower / Wakeups
/ org / freedesktop / UPower / пристрої
/ org / freedesktop / UPower / пристрої / DisplayDevice
/ org / freedesktop / UPower / пристрої / батарея_BAT0
/ org / freedesktop / UPower / пристрої / line_power_ADP0

У мене не qdbusвстановлено, але відповідно до цієї сторінки

qdbus --system org.freedesktop.UPower

має дати подібний результат.


Як створити список шляхів до об’єктів 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, щоб побачити, якими методами, властивостями і т. Д. Володіє кожен об’єкт (натиснувши вкладку).



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.

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


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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.