DBus-Cherrypy合并问题

时间:2009-12-29 19:56:52

标签: python cherrypy dbus

我正在使用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和dbus。

2 个答案:

答案 0 :(得分:3)

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

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

快速入门执行上述操作,但通过调用engine.block()完成。如果你的程序有一些除了CherryPy之外的主循环,省略对engine.block的调用,你应该没问题。但是,当你的外部主循环终止时,你仍然想要调用cherrypy.engine.stop():

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

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

答案 1 :(得分:3)

我想出来了。显然,glib中存在一堆线程争用问题。如果您创建了一个包含DBusGMainLoop的应用程序,那么您无法在应用程序中创建另一个线程。新线程在调用start()时立即阻塞。没有多少按摩会让新线程运行。

我发现一个网站对dbus.mainloop.glib.threads_init()有一个模糊的引用,以及在初始化新线程之前必须如何调用它。但是,尝试这个问题时会发现一个新问题。抛出一个异常,说在调用dbus.mainloop.glib.threads_init()之前必须调用g_thread_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())

天哪真是个噩梦。现在让它变得更好。