2013-06-14 5 views
12

Jestem nowym użytkownikiem serwera tornado. Kiedy uruchamiam serwer sieciowy Tornado przy użyciu python main_tornado.py, to działa. Zobacz poniższy kod.Jak zatrzymać serwer WWW tornada za pomocą ctrl + c?

import tornado.ioloop 
import tornado.web 

class MainHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.write("Hello, world") 

application = tornado.web.Application([ 
    (r"/", MainHandler), 
]) 

if __name__ == "__main__": 
    application.listen(8888) 
    tornado.ioloop.IOLoop.instance().start() 

Po zatrzymaniu serwera za pomocą CTRL + C, wystąpił następujący błąd.

^CTraceback (most recent call last): 
    File "main_tornado.py", line 19, in <module> 
    tornado.ioloop.IOLoop.instance().start() 
    File "/home/nyros/Desktop/NewWeb/venv/lib/python3.2/site-packages/tornado/ioloop.py", line 301, in start 
    event_pairs = self._impl.poll(poll_timeout) 
KeyboardInterrupt 

Proszę rozwiązać mój problem. Dzięki ..

+0

możliwe duplikat [Jak zatrzymać serwer WWW Tornado?] (Http://stackoverflow.com/questions/5375220/how-do-i-stop-tornado-web-server) – Blender

+0

Dlaczego to problem? –

Odpowiedz

21

Możesz zatrzymać główną pętlę Tornado z tornado.ioloop.IOLoop.instance().stop(). Aby mieć ta metoda nazywa po przejściu sygnału z Ctrl + C można okresowo sprawdzać globalną flagę aby sprawdzić, czy główny pętla powinna kończyć i zarejestrować obsługi dla sygnału SIGINT który zmieni wartość tej flagi:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import tornado.ioloop 
import tornado.web 
import signal 
import logging 
from tornado.options import options 

is_closing = False 

def signal_handler(signum, frame): 
    global is_closing 
    logging.info('exiting...') 
    is_closing = True 

def try_exit(): 
    global is_closing 
    if is_closing: 
     # clean up here 
     tornado.ioloop.IOLoop.instance().stop() 
     logging.info('exit success') 

class MainHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.write("Hello, world") 

application = tornado.web.Application([ 
    (r"/", MainHandler), 
]) 

if __name__ == "__main__": 
    tornado.options.parse_command_line() 
    signal.signal(signal.SIGINT, signal_handler) 
    application.listen(8888) 
    tornado.ioloop.PeriodicCallback(try_exit, 100).start() 
    tornado.ioloop.IOLoop.instance().start() 

wyjście:

$ python test.py 
[I 130614 11:19:19 web:1514] 200 GET/(127.0.0.1) 0.56ms 
^C[I 130614 11:19:21 test:14] exiting... 
[I 130614 11:19:21 test:22] exit success 

UPDATE

Właśnie zobaczyłem w pytaniu Tornado long polling requests to proste rozwiązanie:

try: 
    tornado.ioloop.IOLoop.instance().start() 
except KeyboardInterrupt: 
    tornado.ioloop.IOLoop.instance().stop() 

Oczywiście, to jest mniej bezpieczny sposób.

+0

Dzięki za odpowiedź. Twój kod jest doskonały. Korzystam z serwera tornado http.Kiedy naciśnięto ctrl + c, zabicie serwera zajmuje dużo czasu. Jakieś pomysły. – dhana

+0

Prawdopodobnie masz jakieś zadanie blokujące, które musi zostać zakończone przed wywołaniem funkcji 'try_exit()'. Możesz spróbować użyć 'tornado.ioloop.IOLoop.instance(). Stop()' bezpośrednio w procederze obsługi sygnałów, ale wydaje mi się to mniej bezpieczne. Jeśli chcesz brutalnie przerwać nieskończoną pętlę w trakcie przetwarzania, trudno będzie uniknąć komunikatów o błędach. – Nykakin

+0

Oryginalne rozwiązanie (obsługa signal.SIGINT) działa doskonale dla mnie w systemie Windows, ale "UPDATE" do twojej odpowiedzi (po prostu łapanie KeyboardInterrupt) nie działa. Ctrl + C w Windows nie generuje KeyboardInterrupt, a niektóre osoby (jak ja, z kompaktową klawiaturą) nie mają CTRL + Pause Break na swojej klawiaturze. –

2

Kod jest OK. CTRL + C generuje KeyboardInterrupt. Aby zatrzymać serwer, możesz użyć klawiszy CTRL + Pause Break (w oknach) zamiast CTRL + C. W Linuksie CTRL + C generuje również KeyboardInterrupt. Jeśli użyjesz CTRL + Z program zatrzyma się, ale port będzie zajęty.

+0

Kiedy mówisz "CTRL +" zamiast "CTRL + C" ", czy rzeczywiście masz na myśli Control i klawisz" plus "? Ponieważ to nic dla mnie nie znaczy – puk

+0

Przepraszam, zredagowałem tam moje wypowiedzi. –

+1

'CTRL + Z' nie zatrzyma tego, ale po prostu przeniesie proces do tła. – WhyNotHugo

4

Możesz po prostu zatrzymać Toneado ioloop od obsługi sygnału. Powinno być bezpieczne dzięki metodzie add_callback_from_signal(), pętla zdarzeń wyjdzie ładnie, kończąc każde ostatecznie współbieżnie uruchomione zadanie.

import tornado.ioloop 
import tornado.web 
import signal 

class MainHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.write("Hello, world") 

application = tornado.web.Application([ 
    (r"/", MainHandler), 
]) 

def sig_exit(signum, frame): 
    tornado.ioloop.IOLoop.instance().add_callback_from_signal(do_stop) 

def do_stop(signum, frame): 
    tornado.ioloop.IOLoop.instance().stop() 

if __name__ == "__main__": 
    application.listen(8888) 
    signal.signal(signal.SIGINT, sig_exit) 
    tornado.ioloop.IOLoop.instance().start() 
+3

powinno to być naprawdę akceptowaną odpowiedzią zamiast zanieczyszczających globałów. – cowbert

+0

jakikolwiek powód, by nie używać 'lambda' zamiast jawnego definiowania' do_stop'? – cowbert

+0

do_stop() można również wywoływać z innych miejsc. Ale w rzeczywistości może to być lambda. –