use*_*615 2 python dbus python-3.x pyqt5
这是DBus服务的标准示例.
import dbus
import gobject
from dbus import service
# from gi._gobject import MainLoop
from dbus.mainloop.glib import DBusGMainLoop
class DBusServer(service.Object):
def __init__(self, name, object_path):
# super(service.Object, self).__init__(name, object_path)
dbus.service.Object.__init__(self, name, object_path)
@dbus.service.method("com.test", in_signature='s', out_signature="s")
def test(self, args):
return args + " Sent by dbus client"
@dbus.service.method("com.test", in_signature='s', out_signature="s")
def foo(self, args):
return "foo"
bus_loop = DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
session_name = service.BusName("com.test", session_bus)
dbus_server = DBusServer(session_name, "/test")
loop = gobject.MainLoop()
try:
loop.run()
except KeyboardInterrupt:
loop.quit()
Run Code Online (Sandbox Code Playgroud)
我对此处使用的两个主循环有疑问
1.每个主循环或事件循环在此代码中的作用是什么(如果我使用正确的术语.我猜它们都是事件循环)
2.如果我的应用程序不是GUI应用程序为什么我需要gobject mainloop或qt mainloop,因为需要从X11库中捕获用户生成的事件(在Linux的情况下)
3.为什么我不能使用无效的循环而不是gobject主循环(如下所示)
while True:
pass
Run Code Online (Sandbox Code Playgroud)
以下是简要回答的总结,详见最后的细节以获得更多解释.
问题1:
您发布的代码中只使用了一个主循环loop = gobject.MainLoop().它的作用是处理事件,例如发送到您服务的D-Bus消息.
问题2:
您需要一个主循环,以便您的代码不会阻止来自服务之外的D-Bus消息.该dbus-python绑定不具有主循环的实现,所以你需要使用一个主循环从其他图书馆(这也需要一个由支持dbus-python,在这种情况下GLib库).
问题3:
像这样的无限循环将永远不允许执行除特定循环之外的任何代码,并且将无法接收D-Bus消息(或任何其他事件).
细节:
简而言之,当程序中当前没有代码运行时,主循环通常会处理其他事件.在这种情况下,D-Bus的性质要求您的代码有一种方法来处理来自外部源的事件,即D-Bus消息.这就是你需要一个主循环的原因.您可以将事件处理基于您自己编写的循环,只要您在循环中具有可以处理外部事件的代码即可.人们经常将库用于主循环的原因是因为事物在"真实"应用程序或系统中往往变得复杂,并且使用已被其他人多年测试,使用和改进的东西(例如GLib)通常更加健壮.
D-Bus绑定dbus-python以需要使用外部主循环的方式实现,因为它没有自己的mainloop实现.设计库以使用外部主循环的典型原因是让库的用户决定使用哪个mainloop,因为mainloop也可能用于其他事情(例如,处理除D-Bus事件之外的其他事件).这增加了库的潜在使用并减少了作为使用库的副作用而引入的依赖性.
但是,库必须支持选择的主循环,这意味着必须为每个要与库一起使用的主循环提供专门的集成.通常,像这样的库的内部设计将使用一个类/类型,它是mainloop的抽象,因此代码内部不需要知道mainloop已经集成了什么.这减少了需要在库中特定于mainloop实现的代码量.
如果您bus_loop在执行时检查收到的对象:
bus_loop = DBusGMainLoop(set_as_default=True)
Run Code Online (Sandbox Code Playgroud)
...你会看到它是一个类型的对象,dbus.mainloop.NativeMainLoop它是mainloop包装器对象dbus-python.
现在,dbus-python目前只提供GLib主循环的集成,因此上面的讨论在这种情况下变得有点理论化.该方法dbus-python集成了能说会道的主循环是要求用户导入和实例GLib的主循环的包装,像这样:
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
Run Code Online (Sandbox Code Playgroud)
这将创建一个GLib主上下文,稍后由GLib主循环使用它来处理dbus-python与该上下文关联的事件.mainloop集成的最后一部分是要求用户启动GLib主循环.导入并运行gobjectmainloop时,如下所示:
loop = gobject.MainLoop()
loop.run()
Run Code Online (Sandbox Code Playgroud)
mainloop将处理先前创建的上下文中的事件.这是D-Bus绑定dbus-python和GObject绑定gobject(可以访问GLib主循环)之间的"链接" .
简化到极端,可以说在执行时创建和设置上下文:
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
Run Code Online (Sandbox Code Playgroud)
是一个要处理的事件列表,如果它们出现,并且在执行时创建并启动了mainloop:
loop = gobject.MainLoop()
loop.run()
Run Code Online (Sandbox Code Playgroud)
是什么使某些东西检查该列表.GLib用于这两件事的事实使它工作,再简单地说.
如果您想进一步深入研究,请阅读GLib和GMainLoop以及GMainContext以及与这些相关的概念.希望这可以帮助.