사용 가능한 DBus 서비스 목록에 대한 후속 질문 입니다.
다음 파이썬 코드는 사용 가능한 모든 DBus 서비스를 나열합니다.
import dbus
for service in dbus.SystemBus().list_names():
print(service)
파이썬에서 서비스 아래에 객체 경로를 어떻게 나열합니까? 대답이 파이썬과 관련이 없다면 괜찮습니다.
우분투 14.04를 사용하고 있습니다
사용 가능한 DBus 서비스 목록에 대한 후속 질문 입니다.
다음 파이썬 코드는 사용 가능한 모든 DBus 서비스를 나열합니다.
import dbus
for service in dbus.SystemBus().list_names():
print(service)
파이썬에서 서비스 아래에 객체 경로를 어떻게 나열합니까? 대답이 파이썬과 관련이 없다면 괜찮습니다.
우분투 14.04를 사용하고 있습니다
답변:
다양한 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 내부 검사 --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')
무엇입니까?
k = rec_intro(bus, 'org.freedesktop.UPower', '/org/freedesktop/UPower')
. 기능을 약간 수정하여 가능하다고 가정합니다.
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
mylist=[]
한 후 교체 print
와 함께 mylist.append
그 기능 블록의 마지막 명령으로 다음과 return mylist
거의가 무엇 스크립트의 맨 아래에 예를 들어, 추가 목록 위나 무엇으로 반복 한 후 수 ... - 접두사로 for x in mylist: print("OBJ_PATH", x)
인쇄하도록 OBJ_PATH
...
파이썬에서 프로그래밍 방식 으로이 작업을 수행 할 수 있는지 확실하지 않습니다. 당신은 할 수 있지만 어떻게 알아내는 것은 큰 두통이 될 것입니다. 나는 전에 그것을 시도하고 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의 인터프리터를 통해 각 객체의 메소드, 속성 등을 확인하려면 탭을 누르십시오.
서비스에 구현하는 객체가있는 경우 org.freedesktop.DBus.ObjectManager
해당 메소드 GetManagedObjects
는 "단일 메소드 호출로 모든 객체, 인터페이스 및 속성"을 반환합니다 . 예를 들어 UDisks2에는 이러한 객체가 있습니다.
버스 이름 (서비스)의 객체 경로를 얻는 경험에서 내가 아는 것 객체 경로 '/'를 검사 할 수 있습니다 (예 : 위의 예제 사용)
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.
객체 경로 '/'가 루트이고 모든 노드가 하위 폴더 인 하드 드라이브의 폴더 구조를 거치는 것과 같습니다. 이것은 특정 버스 이름 (서비스)의 오브젝트 경로를 검색하고 오브젝트 경로를 포함하는 콜렉션을 구성하는 가장 좋은 방법 인 것 같습니다.
#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)