2009-07-02 54 views
7

我有一個應用程序在啓動一些其他線程(包括CherryPy Web服務器)後,在我的主線程中啓動反應器並運行reactor.run()來運行Twisted。下面是當按下Ctrl + C鍵的Linux,但無法在Windows乾淨關閉的程序:CherryPy干擾在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從信號處理程序將執行(我已驗證信號處理程序本身確實被調用)

我該怎麼做?如何在運行CherryPy時從信號處理程序關閉Windows上的Twisted?這是一個錯誤,還是我錯過了這兩個項目中任何一個的重要部分?

回答

14

當您調用快速啓動時,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() 
+3

非常感謝!你的回答寫得非常好,而且樂於助人,所以我爲了給你50個聲望開了一個獎勵。 – 2009-07-06 14:08:48