基本上问题是,获取VLC所有实例的唯一方法是搜索所有非命名实例以获取org.freedesktop.MediaPlayer标识函数并调用它。
(或者我可以使用内省API,但这似乎不能解决我的问题) 不幸的是,许多程序在发送dbus呼叫后,根本就没有响应,导致长时间和昂贵的超时。
当这种情况多次发生时,它可以累加起来。 基本上内置超时时间过长。
如果我能以某种方式减少dbus超时,这将解决我的问题,但理想的解决方案将是一种方式。
我认为我可以将每个调用放入一个线程中的“识别”并且我可以杀死花费太长时间的线程,但这似乎没有被建议。另外,添加多线程会大大增加CPU负载,同时又不会提高程序的速度。
这是我试图快速运行的代码(或多或少),目前速度很慢。
import dbus
bus = dbus.SessionBus()
dbus_proxy = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
names = dbus_proxy.ListNames()
for name in names:
if name.startswith(':'):
try:
proxy = bus.get_object(name, '/')
ident_method = proxy.get_dbus_method("Identity",
dbus_interface="org.freedesktop.MediaPlayer")
print ident_method()
except dbus.exceptions.DBusException:
pass
答案 0 :(得分:1)
比产生一堆线程更容易的是异步调用不同的服务,为结果返回或发生D-Bus错误提供回调处理程序。所有的调用都是有效地并行发生的,一旦得到一些积极的结果,你的程序就可以继续进行。
这是一个快速而肮脏的程序,它打印出它找到的所有服务的列表。请注意,无需等待任何超时,它能获得所有积极结果的速度有多快。在一个真实的程序中,你可能会给错误处理程序分配一个无操作函数,因为你的目标是忽略那些没有响应的服务,但这个例子一直等到它在退出之前就听到了。
#! /usr/bin/env python
import dbus
import dbus.mainloop.glib
import functools
import glib
class VlcFinder (object):
def __init__ (self, mainloop):
self.outstanding = 0
self.mainloop = mainloop
bus = dbus.SessionBus ()
dbus_proxy = bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
names = dbus_proxy.ListNames ()
for name in dbus_proxy.ListNames ():
if name.startswith (":"):
proxy = bus.get_object (name, "/")
iface = dbus.Interface (proxy, "org.freedesktop.MediaPlayer")
iface.Identity (reply_handler = functools.partial (self.reply_cb, name),
error_handler = functools.partial (self.error_cb, name))
self.outstanding += 1
def reply_cb (self, name, ver):
print "Found {0}: {1}".format (name, ver)
self.received_result ()
def error_cb (self, name, msg):
self.received_result ()
def received_result (self):
self.outstanding -= 1
if self.outstanding == 0:
self.mainloop.quit ()
if __name__ == "__main__":
dbus.mainloop.glib.DBusGMainLoop (set_as_default = True)
mainloop = glib.MainLoop ()
finder = VlcFinder (mainloop)
mainloop.run ()