CherryPy препятствует скрученному завершению работы Windows
Вопрос
У меня есть приложение, которое запускается Twisted путем запуска реактора с reactor.run()
в моем основном потоке после запуска некоторых других потоков, включая веб-сервер CherryPy.Вот программа, которая полностью завершает работу при нажатии Ctrl + C в Linux, но не в 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, которая выполняет чистое завершение работы как в Linux, так и в Windows при нажатии Ctrl + C:
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()
У кого-нибудь есть какие-нибудь идеи, в чем проблема?Вот моя головоломка:
- В Linux все работает
- В Windows я могу вызывать функции из обработчиков сигналов, используя
reactor.callFromThread
когда CherryPy не запущен - Когда CherryPy запущен, ни одна функция, которую я вызываю с помощью
reactor.callFromThread
из обработчика сигнала, который когда-либо будет выполняться (я проверил, что сам обработчик сигнала действительно вызывается)
Что я могу с этим поделать?Как я могу отключить Twisted в Windows из обработчика сигналов во время запуска CherryPy?Это ошибка, или я просто пропустил какую-то важную часть документации для любого из этих двух проектов?
Решение
CherryPy обрабатывает сигналы по умолчанию при вызове quickstart.В вашем случае вам, вероятно, следует просто развернуть quickstart, который состоит всего из нескольких строк, и выбирать.Вот в основном то, что 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()
В вашем случае вам не нужны обработчики сигналов, поэтому вы можете их опустить.Вам также не нужно вызывать engine.block, если вы не запускаете CherryPy из основного потока.Engine.block() - это просто способ заставить основной поток не завершаться немедленно, а вместо этого подождать завершения процесса (это для того, чтобы автоматическая загрузка работала надежно;на некоторых платформах возникают проблемы с вызовом execv из любого потока, кроме основного).
Если вы удалите вызов block(), вам даже не понадобится Thread() вокруг quickstart.Итак, замените свою строку:
Thread(target=cherrypy.quickstart, args=[Root()]).start()
с:
cherrypy.tree.mount(Root())
cherrypy.engine.start()