我开始使用DBus和事件驱动编程。我正在尝试创建的服务实际上由三部分组成,但其中两部分实际上是“服务器”。
1)实际的DBus服务器通过HTTPS与远程网站通信,管理会话,并向客户传达信息。
2)服务的另一部分每2分钟调用一个保持活动页面,以使会话在外部网站上保持活动状态
3)客户端调用服务以从服务中检索信息。
我找到了一些简单的示例程序。我正在努力使它们适应原型#1和#2。而不是为两者构建单独的程序。我以为我可以在单个双线程进程中运行它们。
我看到的问题是我在保持活动线程中调用time.sleep(X)。线程进入睡眠状态,但不会醒来。我认为GIL不会被GLib主循环释放。
这是我的线程代码:
class Keepalive(threading.Thread):
def __init__(self, interval=60):
super(Keepalive, self).__init__()
self.interval = interval
bus = dbus.SessionBus()
self.remote = bus.get_object("com.example.SampleService", "/SomeObject")
def run(self):
while True:
print('sleep %i' % self.interval)
time.sleep(self.interval)
print('sleep done')
reply_status = self.remote.keepalive()
if reply_status:
print('Keepalive: Success')
else:
print('Keepalive: Failure')
从印刷声明中,我知道睡眠开始,但我从未看到“完成睡眠。”
这是主要代码:
if __name__ == '__main__':
try:
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
name = dbus.service.BusName("com.example.SampleService", session_bus)
object = SomeObject(session_bus, '/SomeObject')
mainloop = gobject.MainLoop()
ka = Keepalive(15)
ka.start()
print('Begin main loop')
mainloop.run()
except Exception as e:
print(e)
finally:
ka.join()
其他一些观察结果:
我看到“开始主循环”消息,所以我知道它正在获得控制权。然后,我看到“睡觉%i”,之后,没有。
如果我^ C,那么我看到“完成睡眠”。大约20秒后,我从self.run()得到一个异常,远程应用程序没有响应:
DBusException:org.freedesktop.DBus.Error.NoReply:没有收到回复。可能的原因包括:远程应用程序未发送回复,消息总线安全策略阻止了回复,回复超时已过期,或网络连接中断。
在服务器中运行保持活动代码的最佳方法是什么?
谢谢,
答案 0 :(得分:6)
通过调用gobject
使用gobject.threads_init()
时,必须显式启用多线程。有关背景信息,请参阅PyGTK FAQ。
接下来,就你所描述的目的而言,超时似乎更合适。使用方法如下:
# Enable timer
self.timer = gobject.timeout_add(time_in_ms, self.remote.keepalive)
# Disable timer
gobject.source_remove(self.timer)
每keepalive
(毫秒)调用time_in_ms
函数。有关详细信息,请参阅PyGTK reference。