python - 主循环,事件循环在DBus服务中的作用

标签 python python-3.x dbus 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()

我对这里使用的两个主循环有疑问
一。在这段代码中,每个主循环或事件循环的作用是什么(如果我使用正确的术语的话)。我猜它们都是事件循环)
2。如果我的应用程序不是GUI应用程序,为什么我需要gobject mainloop或qt mainloop,因为这是从X11库捕获用户生成的事件所必需的(对于Linux)
三。为什么我不能使用一个不做任何事情的无限循环来代替gobject主循环(如下所示)
while True:
    pass

最佳答案

以下是总结的简短答案,请参阅最后的详细说明。
问题1:
您发布的代码中只使用了一个主循环loop = gobject.MainLoop()。它的作用是处理事件,例如发送给您的服务的D-Bus消息。
问题2:
您需要一个主循环,以便您的代码不阻止来自服务外部的D-Bus消息。dbus-python绑定没有mainloop实现,因此需要使用其他库中的mainloop(在本例中,GLib也需要由dbus-python支持)。
问题3:
这样的无限循环永远不允许执行除该特定循环之外的任何代码,也不可能接收D总线消息(或任何其他事件)。
细节:
简单地说,当程序中当前没有运行代码时,主循环通常会处理其他事件。在这种情况下,D-Bus的本质要求代码有一种方法来处理来自外部源的事件,即D-Bus消息。这就是你需要一个主循环的原因。只要循环中有可以处理外部事件的代码,就可以将事件处理基于您自己编写的循环。人们经常在主循环中使用库的原因是,在“真实”的应用程序或系统中,事情往往变得越来越复杂,而且使用别人多年来测试、使用和改进过的东西(例如GLib)往往更加健壮。
D-Bus绑定dbus-python的实现方式需要使用外部主循环,因为它没有自己的主循环实现。将库设计为使用外部主循环的一个典型原因是,让库的用户决定使用哪个主循环,因为主循环也可能用于其他事情(例如处理除D-Bus事件以外的其他事件)。这增加了库的潜在使用,并减少了作为使用库的副作用而引入的依赖关系。
但是,库必须支持选择的主循环,这意味着必须为每个打算与库一起使用的主循环提供一些集成。通常,这样的库的内部将被设计为使用一个类/类型,该类/类型是主循环的抽象,因此代码内部不需要知道集成了什么主循环。这减少了库中需要特定于主循环实现的代码量。
如果检查执行时接收的bus_loop对象:

bus_loop = DBusGMainLoop(set_as_default=True)

... 您将看到它是dbus.mainloop.NativeMainLoop类型的对象,它是dbus-python中的主循环包装器对象。
现在,dbus-python目前只为GLib主循环提供了一个集成,因此在这种情况下,上面的讨论变得有点理论化。集成GLib mainloop的方法是要求用户导入并实例化GLib mainloop包装器,如下所示:
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)

这将创建一个GLib主上下文,GLib主循环稍后将使用它来处理与该上下文关联的事件。主循环集成的最后一部分是要求用户启动一个GLib主循环。当导入并运行dbus-pythonmain循环时,如下所示:
loop = gobject.MainLoop()
loop.run()

主循环将处理先前创建的上下文中的事件。这是D-Bus绑定dbus-python和GObject绑定gobject之间的“链接”(允许访问GLib主循环)。
简化到极致,可以说上下文是在执行以下操作时创建和设置的:
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)

是要处理的事件列表(如果它们出现),并且在执行以下操作时创建并启动主循环:
loop = gobject.MainLoop()
loop.run()

是什么让事情检查清单。事实上,GLib同时用于这两个方面,这使得它可以工作,简单地说。
如果你想深入研究这个问题,请阅读GLib、GMainLoop和GMainContext以及与之相关的概念。希望这有帮助。

关于python - 主循环,事件循环在DBus服务中的作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33428804/

相关文章:

python - 使用python扩展字符串中的环境变量

python - 匹配 BeautifulSoup 中的部分 id

用于被覆盖的属性和方法的 Python 命名约定

python - 如何让 Python 请求信任自签名 SSL 证书?

python-3.x - NetCDF4 python创建numpy多维数组

python - 我应该如何以及在哪里创建此事务方法?

python-3.x - 将 python 列表传递给 keras model.fit

python - 在python中向dbus对象添加方法

linux - 将密码安全地传递给另一个程序(单独的 shell/dbus)

python - 如何公开具有多个参数的 dbus 方法?