2009-07-02 14 views
7

CherryPy Webサーバーを含む他のスレッドを起動した後にメインスレッドでreactor.run()という反応装置を起動してTwistedを実行するアプリケーションを取得しました。CherryPyがWindowsのTwistedシャットダウンを妨げる

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は、Windows上でLinux上ではなく、押されたときに正常にシャットダウンプログラムです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() 

問題が何であるか分かりませんか? CherryPyには、私からreactor.callFromThreadを使用して通話何の機能も実行されていない場合はCherryPyには

  • を実行していないとき、私はreactor.callFromThreadを使用してシグナルハンドラから関数を呼び出すことができ、のLinuxのすべてで

    • は、Windows上で
    • に動作します:ここに私の難問ですシグナルハンドラが実行されます(シグナルハンドラ自体が呼び出されたことを確認しました)

    私はこれについて何ができますか? CherryPyの実行中に信号ハンドラからWindows上でTwistedをシャットダウンする方法はありますか?これはバグですか?あるいは、この2つのプロジェクトのいずれかのドキュメントの重要な部分を見逃しただけですか?

  • 答えて

    14

    CherryPyは、quickstartを呼び出すと、デフォルトで信号を処理します。あなたの場合、たぶん数行しかないクイックスタートを展開し、選択して選ぶべきでしょう。ここではクイックスタートがトランクに何をするかは基本的です:あなたのケースでは

    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を呼び出す問題があります)。

    ブロック()コールを削除すると、クイックスタートの周りにもThread()は必要ありません。だから、あなたの行を置き換える:

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

    で:

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

    ありがとうを!あなたの答えは非常によく書かれており、私はあなたに50の評判を与えるために恩恵を始めました。 –

    関連する問題