我有一个运行Twisted的应用程序,在启动其他线程(包括CherryPy Web服务器)后,在我的主线程中使用reactor.run()
启动reactor。这是一个在Linux上按下Ctrl + C但在Windows上没有按下时干净地关闭的程序:
from threading import Thread
from signal import signal, SIGINT
import cherrypy
from twisted.internet import reactor
from twisted.web.client import getPage
def stop(signum, frame):
cherrypy.engine.exit()
reactor.callFromThread(reactor.stop)
signal(SIGINT, stop)
class Root:
@cherrypy.expose
def index(self):
reactor.callFromThread(kickoff)
return "Hello World!"
cherrypy.server.socket_host = "0.0.0.0"
Thread(target=cherrypy.quickstart, args=[Root()]).start()
def print_page(html):
print(html)
def kickoff():
getPage("http://acpstats/account/login").addCallback(print_page)
reactor.run()
我认为CherryPy是罪魁祸首,因为这是我在没有CherryPy的情况下编写的另一个程序,当按下Ctrl + C时,它会在Linux和Windows上完全关闭:
from time import sleep
from threading import Thread
from signal import signal, SIGINT
from twisted.internet import reactor
from twisted.web.client import getPage
keep_going = True
def stop(signum, frame):
global keep_going
keep_going = False
reactor.callFromThread(reactor.stop)
signal(SIGINT, stop)
def print_page(html):
print(html)
def kickoff():
getPage("http://acpstats/account/login").addCallback(print_page)
def periodic_downloader():
while keep_going:
reactor.callFromThread(kickoff)
sleep(5)
Thread(target=periodic_downloader).start()
reactor.run()
有谁知道问题是什么?这是我的难题:
reactor.callFromThread
从信号处理程序调用函数reactor.callFromThread
调用的函数都不会执行(我已经验证了信号处理程序本身会被调用)我该怎么办?如何在运行CherryPy时从信号处理程序关闭Windows上的Twisted?这是一个错误,还是我错过了这两个项目中任何一个文档的重要部分?
答案 0 :(得分:14)
当您调用quickstart时,CherryPy会默认处理信号。在您的情况下,您可能只需要展开quickstart,这只是几行,然后挑选。这里基本上是快速启动在trunk中的作用:
if config:
cherrypy.config.update(config)
tree.mount(root, script_name, config)
if hasattr(engine, "signal_handler"):
engine.signal_handler.subscribe()
if hasattr(engine, "console_control_handler"):
engine.console_control_handler.subscribe()
engine.start()
engine.block()
在您的情况下,您不需要信号处理程序,因此您可以省略它们。如果你没有从主线程启动CherryPy,你也不需要调用engine.block。 Engine.block()只是让主线程不会立即终止的一种方法,而是等待进程终止(这样可以自动运行可靠;某些平台有问题从主线程的任何线程调用execv)。
如果删除block()调用,则甚至不需要快速启动周围的Thread()。所以,替换你的行:
Thread(target=cherrypy.quickstart, args=[Root()]).start()
使用:
cherrypy.tree.mount(Root())
cherrypy.engine.start()