CherryPy препятствует скрученному завершению работы Windows

StackOverflow https://stackoverflow.com/questions/1075351

Вопрос

У меня есть приложение, которое запускается 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()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top