dbus 서비스에서 모든 객체 경로를 나열하는 방법은 무엇입니까?


16

사용 가능한 DBus 서비스 목록에 대한 후속 질문 입니다.

다음 파이썬 코드는 사용 가능한 모든 DBus 서비스를 나열합니다.

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

파이썬에서 서비스 아래에 객체 경로를 어떻게 나열합니까? 대답이 파이썬과 관련이 없다면 괜찮습니다.

우분투 14.04를 사용하고 있습니다


대답이 파이썬과 관련이 없다면 괜찮습니다.
user768421

답변:


15

표준 문서에 따라 공식 문서에 따라 :

다양한 D-Bus 애플리케이션에 유용 할 수있는 일부 표준 인터페이스가 있습니다.

org.freedesktop.DBus.Introspectable

이 인터페이스에는 한 가지 방법이 있습니다.

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

인터페이스 (신호 및 메소드 포함), 객체 경로 트리에서 객체 아래의 객체 및 속성을 포함하여 객체 IntrospectXML 설명 을 반환하는 객체 인스턴스가 구현 될 수 있습니다.

여기에 시작해야 할 매우 간단한 예가 있습니다. 그것은 사용 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 내부 검사 --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 / 장치
/ org / freedesktop / UPower / devices / DisplayDevice
/ org / freedesktop / UPower / devices / battery_BAT0
/ org / freedesktop / UPower / devices / line_power_ADP0

qdbus설치 하지 않았지만 이 페이지 에 따라

qdbus --system org.freedesktop.UPower

비슷한 결과를 가져와야합니다.


에서 객체 경로 목록을 작성하는 방법은 rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')무엇입니까?
Khurshid Alam

아니요, 파이썬으로 객체 경로 목록을 생성하여 특정 객체 경로가 목록에 있는지 (스크립트에서) 확인할 수 있습니다. 그것은 객체 경로를 올바르게 인쇄합니다., 그러나 나는 무언가를 원합니다 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

파이썬에서 프로그래밍 방식 으로이 작업을 수행 할 수 있는지 확실하지 않습니다. 당신은 할 수 있지만 어떻게 알아내는 것은 큰 두통이 될 것입니다. 나는 전에 그것을 시도하고 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의 인터프리터를 통해 각 객체의 메소드, 속성 등을 확인하려면 탭을 누르십시오.



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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.