修改CherryPy的关机程序

时间:2016-09-23 10:29:08

标签: python multithreading webserver cherrypy

所以我有一个包装状态机的樱桃py服务器。在幕后,这个状态机完成了所有繁重的mananging进程和线程以及缓存,并且它是线程安全的。所以在启动我的樱桃py时,我将它附加到应用程序,请求调用app.state_machine.methods。

在伪代码中我做:

from flask_app import app
import cherrypy

#configure app

app.state_machine = State_Machine.start()
try:
    cherrypy.tree.graft(app, "/")
    cherrypy.server.unsubscribe()

    server = cherrypy._cpserver.Server()
    server.socket_host="0.0.0.0"
    server.socket_port = 5001
    server.thread_pool = 10
    server.subscribe()

    cherrypy.engine.start()
    cherrypy.engine.block()
except KeyboardInterrupt:
    logging.getLogger(__name__).warn("Recieved keyboard interrupt")
except Exception:
    logging.getLogger(__name__).exception("Unknown exception from app")
finally:
    logging.getLogger(__name__).info("Entering Finally Block")
    state_machine.shutdown()

这里的意图是键盘中断应该传播出应用程序并调用state_machine.shutdown,它可以用于例如:烧瓶开发服务器。

然而,cherrypy吞下KeyBoard中断并等待其子线程关闭,因为它们包含对app.state_machine的引用,它们将无限期地死锁,直到调用app.state_machine.shutdown()为止。

那么如何修改cherrypy的关闭程序,使其正确关闭?

1 个答案:

答案 0 :(得分:0)

正如网络忍者所建议的,答案是使用插件。

from cherrypy.process import wspbus, plugins

class StateMachinePlugin(plugins.SimplePlugin) :

    def __init__(self, bus, state_machine):
        plugins.SimplePlugin.__init__(self, bus)
        self.state_manager = state_machine

    def start(self):
        self.bus.log("Starting state_machine")
        self.state_machine.run()

    def stop(self):
        self.bus.log("Shutting down state_machine")
        self.state_machine.shutdown()
        self.bus.log("Successfully shut down state_machine")

然后就这样做:

from flask_app import app
import cherrypy

#configure app

app.state_machine = State_Machine.start()
try:
    cherrypy.tree.graft(app, "/")
    cherrypy.server.unsubscribe()

    server = cherrypy._cpserver.Server()
    server.socket_host="0.0.0.0"
    server.socket_port = 5001
    server.thread_pool = 10
    server.subscribe()

 ###########################Added This line####################
 StateMachinePlugin(cherrypy.engine, app.state_machine).subscribe()
 #####################End Additions##########################

    cherrypy.engine.start()
    cherrypy.engine.block()
except KeyboardInterrupt:
     logging.getLogger(__name__).warn("Recieved keyboard interrupt")
except Exception:
     logging.getLogger(__name__).exception("Unknown exception from app")
finally:
    logging.getLogger(__name__).info("Entering Finally Block")
    state_machine.shutdown()