【问题标题】:CherryPy interferes with Twisted shutting down on WindowsCherryPy 干扰了 Windows 上的 Twisted 关闭
【发布时间】:2010-11-07 16:51:38
【问题描述】:

在启动其他一些线程(包括 CherryPy Web 服务器)后,我有一个运行 Twisted 的应用程序,方法是在我的主线程中使用 reactor.run() 启动反应器。这是一个程序,当在 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?这是一个错误,还是我只是错过了这两个项目的文档中的一些重要部分?

【问题讨论】:

    标签: python windows linux twisted cherrypy


    【解决方案1】:

    当您调用 quickstart 时,CherryPy 默认处理信号。在您的情况下,您可能应该只展开只有几行的快速入门,然后进行选择。这基本上是快速入门在主干中所做的:

    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() 只是一种使主线程不立即终止的方法,而是等待进程终止(这样 autoreload 才能可靠地工作;某些平台在从除主线程之外的任何线程调用 execv 时存在问题)。

    如果您删除 block() 调用,您甚至不需要快速启动中的 Thread()。所以,替换你的行:

    Thread(target=cherrypy.quickstart, args=[Root()]).start()
    

    与:

    cherrypy.tree.mount(Root())
    cherrypy.engine.start()
    

    【讨论】:

    • 非常感谢!你的回答写得很好,很有帮助,我开始赏金只是为了给你 50 声望。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    相关资源
    最近更新 更多