0

python-dbusとcherrypyを使用してUSBデバイスを監視し、挿入されたUSBデバイスのステータスを維持するRESTサービスを提供しています。私はこれらのサービスを個別に作成およびデバッグしましたが、期待どおりに機能します。

今、私はサービスを単一のアプリケーションにマージしています。私の問題は、両方のサービス(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の両方を初期化します。

4

2 に答える 2

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()ソースコードを参照してください。

于 2009-12-30T01:45:13.407 に答える
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())

なんて悪夢だ。今それをより良くするために。

于 2009-12-31T00:03:59.963 に答える