【问题标题】:DBus-Cherrypy merge issueDBus-Cherrypy 合并问题
【发布时间】:2010-12-30 21:39:40
【问题描述】:

我正在使用 python-dbus 和 cherrypy 来监控 USB 设备并提供 REST 服务来维护插入的 USB 设备的状态。我已经独立编写和调试了这些服务,它们按预期工作。

现在,我将这些服务合并到一个应用程序中。我的问题是: 我似乎无法同时启动两种服务(cherrypy 和 dbus)。一个或另一个阻塞或超出范围,或未初始化。

我已经尝试将每个都封装在自己的线程中,然后对它们调用 start 。这有一些奇怪的问题。

class RESTThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        cherrypy.config.update({ 'server.socket_host': HVR_Common.DBUS_SERVER_ADDR, 'server.socket_port': HVR_Common.DBUS_SERVER_PORT, })
        cherrypy.quickstart(USBRest())

class DBUSThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        DBusGMainLoop(set_as_default=True)
        loop = gobject.MainLoop()
        DeviceAddedListener()
        print 'Starting DBus'
        loop.run()

print 'DBus Python Started'
if __name__ == '__main__':
    # Start up REST

    print 'Starting REST'
    rs = RESTThread()
    rs.start()

    db = DBUSThread()
    db.start()

    #cherrypy.config.update({ 'server.socket_host': HVR_Common.DBUS_SERVER_ADDR, 'server.socket_port': HVR_Common.DBUS_SERVER_PORT, })
    #cherrypy.quickstart(USBRest())

    while True:
        x = 1

运行此代码时,cherrypy 代码未完全初始化。当插入 USB 设备时,cherrypy 继续初始化(好像线程以某种方式链接),但不起作用(不提供数据甚至在端口上建立连接)我查看了 cherrypys wiki 页面但是还没有找到一种启动cherrypy的方法,它可以初始化并返回,所以我可以初始化DBus的东西并能够把它拿出来。

我的终极问题是:有没有办法让cherrypy 启动而不阻塞但继续工作?我想摆脱这个例子中的线程,并在主线程中初始化cherrypy和dbus。

【问题讨论】:

标签: python cherrypy dbus


【解决方案1】:

是的;不要使用cherrypy.quickstart。相反,解压它:

cherrypy.config.update(conf)
cherrypy.tree.mount(USBREST())
cherrypy.engine.start()

Quickstart 执行上述操作,但通过调用 engine.block() 完成。如果您的程序有 CherryPy 以外的其他主循环,请省略对 engine.block 的调用,您应该没问题。但是,当您的外部主循环终止时,您仍然需要调用cherrypy.engine.stop():

loop = gobject.MainLoop()
try:
    loop.run()
finally:
    cherrypy.engine.stop()

还有一些其他的问题,比如 CherryPy 是否应该处理 Ctrl-C 和其他信号,以及它是否应该自动重新加载。这些行为取决于您,并且都相当容易启用/禁用。查看其中一些的cherrypy.quickstart() 源代码。

【讨论】:

  • 我试过这个,几种方法都没有成功。我确实设法找出问题所在。显然,在进行一系列 thread_init() 调用之前,启动一个 glib 循环(对于 DBus messenger )不会让任何其他线程在应用程序中启动。我将在原帖中详细说明这一点。您的解决方案适用于不存在新 glib 循环的情况。
【解决方案2】:

我想通了。显然,glib 中有一堆线程争用问题。如果您制作的应用程序中包含 DBusGMainLoop,则您无法在应用程序中创建另一个线程。新线程在调用 start() 时立即阻塞。再多的按摩也不会让新线程运行。

我发现一个站点对 dbus.mainloop.glib.threads_init() 有一个模糊的引用,以及在初始化新线程之前必须如何调用它。然而,当尝试这样做时,发现了一个新问题。抛出一个异常,说 g_thread_init() 必须在 dbus.mainloop.glib.threads_init() 被调用之前被调用。更多搜索发现了对 gobject.threads_init() 的另一个模糊引用。它似乎很合适,所以经过多次实验,我发现了正确的顺序。

这是解决方案。

dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
gobject.threads_init()
dbus.mainloop.glib.threads_init()    
DBUSMAINLOOP = gobject.MainLoop()

print 'Creating DBus Thread'
DBUSLOOPTHREAD = threading.Thread(name='glib_mainloop', target=DBUSMAINLOOP.run)
DBUSLOOPTHREAD.start()

print 'Starting REST'
cherrypy.config.update({ 'server.socket_host': Common.DBUS_SERVER_ADDR, 'server.socket_port': Common.DBUS_SERVER_PORT, })
cherrypy.quickstart(USBRest())

天哪,真是一场噩梦。现在让它变得更好。

【讨论】:

    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 2013-11-05
    • 2012-01-05
    • 1970-01-01
    • 2013-11-26
    • 2011-02-26
    • 1970-01-01
    • 2021-06-02
    相关资源
    最近更新 更多