จะแสดงรายการเส้นทางของวัตถุทั้งหมดภายใต้บริการ dbus ได้อย่างไร


16

นี่คือคำถามที่ติดตามรายการของบริการ DBus ใช้ได้

รหัสหลามต่อไปนี้จะแสดงรายการบริการ DBus ที่มีอยู่ทั้งหมด

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

เราจะแสดงรายการเส้นทางวัตถุภายใต้บริการในหลามได้อย่างไร มันก็โอเคถ้าคำตอบไม่เกี่ยวข้องกับงูหลามแม้ว่ามันจะเป็นที่ต้องการ

ฉันใช้ Ubuntu 14.04


มันก็โอเคถ้าคำตอบไม่เกี่ยวข้องกับงูหลามแม้ว่ามันจะเป็นที่ต้องการ
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 - ระบบ - จุดสุดยอด org.freedesktop.UPower - object-path \
/ org / freedesktop / UPower --recurse | awk '/ ^ * node / {print $ 2}'
/ org / freedesktop / UPower
/ org / freedesktop / UPower / wakeups
/ org / freedesktop / UPower / อุปกรณ์
/ org / freedesktop / UPower / อุปกรณ์ / DisplayDevice
/ org / freedesktop / UPower / อุปกรณ์ / battery_BAT0
/ org / freedesktop / UPower / อุปกรณ์ / line_power_ADP0

ฉันไม่ได้qdbusติดตั้ง แต่อ้างอิงจากหน้านี้

qdbus --system org.freedesktop.UPower

ควรให้ผลลัพธ์ที่คล้ายกัน


ฉันจะสร้างรายการของเส้นทางวัตถุได้rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')อย่างไร
Khurshid Alam

ไม่ฉันหมายถึงการสร้างรายการเส้นทางของวัตถุหลามเพื่อให้ฉันสามารถตรวจสอบ (ในสคริปต์ของฉัน) หากมีเส้นทางวัตถุเฉพาะในรายการ มันพิมพ์เป็นไร objectpath ได้. k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')แต่ฉันต้องการสิ่งที่ต้องการ ฉันคิดว่ามันเป็นไปได้โดยการปรับเปลี่ยนฟังก์ชั่นเล็กน้อย
Khurshid Alam

โค้ดตัวอย่างที่มี 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 - เริ่มต้นรายการก่อนฟังก์ชั่นเช่นmylist=[]แทนที่printด้วยmylist.appendแล้วเป็นคำสั่งสุดท้ายในบล็อกฟังก์ชั่นreturn mylist- นั่นคือสิ่งที่มี ... คุณสามารถทำซ้ำในรายการหรือสิ่งอื่น ๆ เช่นเพิ่มที่ด้านล่างของสคริปต์for x in mylist: print("OBJ_PATH", x)พวกเขาจะมีการพิมพ์ด้วยOBJ_PATHคำนำหน้า ...
don_crissti

4

ฉันไม่แน่ใจว่าคุณสามารถทำสิ่งนี้ได้ทางโปรแกรมใน Python คุณอาจจะ แต่มันจะปวดหัวมากที่จะคิดออกว่า ฉันพยายามทำมาก่อนและจบลงด้วยการเกลียดชัง Dbus อย่างไรก็ตามฉันแนะนำให้ใช้d-feetถ้าคุณต้องการตรวจสอบสิ่งต่าง ๆ ด้านล่างนี้เป็นภาพหน้าจอที่ผมขโมยไปจากฉันบล็อก

ป้อนคำอธิบายรูปภาพที่นี่

เมื่อคุณทราบชื่อโปรแกรม, เส้นทางวัตถุ ฯลฯ คุณสามารถใช้ 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!

ดังนั้นใช้เครื่องมือ GUI เพื่อค้นหาเส้นทางวัตถุอินเตอร์เฟส ฯลฯ จากนั้นใช้โค้ดขนาดเล็กด้านบนเป็นเทมเพลตเพื่อเข้าถึงสิ่งเหล่านั้น นอกจากนี้ฉันขอแนะนำให้คุณทำเช่นนี้ผ่านล่ามของ IPython เพื่อดูวิธีการคุณสมบัติและอื่น ๆ แต่ละวัตถุมี (โดยการกดปุ่ม Tab)


2

หากบริการมีการใช้วัตถุorg.freedesktop.DBus.ObjectManagerวิธีการของมันGetManagedObjectsจะส่งกลับ“ วัตถุทั้งหมดอินเตอร์เฟสและคุณสมบัติในการเรียกใช้วิธีการเดียว”ตัวอย่างเช่น UDisks2 มีวัตถุดังกล่าว


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>

ตามด้วยวิปัสสนาของเส้นทาง / /

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.