CherryPy干扰Windows上的Twisted关闭

时间:2009-07-02 16:25:06

标签: python windows linux twisted cherrypy

我有一个运行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()

有谁知道问题是什么?这是我的难题:

  • 在Linux上一切正常
  • 在Windows上,当CherryPy未运行时,我可以使用reactor.callFromThread从信号处理程序调用函数
  • 当CherryPy运行时,我从信号处理程序中使用reactor.callFromThread调用的函数都不会执行(我已经验证了信号处理程序本身会被调用)

我该怎么办?如何在运行CherryPy时从信号处理程序关闭Windows上的Twisted?这是一个错误,还是我错过了这两个项目中任何一个文档的重要部分?

1 个答案:

答案 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()