相关文章推荐
乖乖的香菜  ·  MECHREVO 机械革命 S1 Pro ...·  3 月前    · 
想出国的大象  ·  AttributeError: ...·  4 月前    · 
买醉的墨镜  ·  Anaconda ...·  1 年前    · 
踏实的韭菜  ·  深入解析 Cron ...·  1 年前    · 

I am new to tornado web server. When I start the tornado web server using python main_tornado.py It is working. Please see the below code.

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

When I stop the server using CTRL+C it gave the following error.

    ^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

Please solve my problem. Thanks..

You can stop Tornado main loop with tornado.ioloop.IOLoop.instance().stop(). To have this method called after passing signal with Ctrl+C you can periodically check global flag to test if main loop should end and register handler for SIGINT signal which will change value of this flag:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import signal
import logging
import tornado.ioloop
import tornado.web
import tornado.options
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")
class MyApplication(tornado.web.Application):
    is_closing = False
    def signal_handler(self, signum, frame):
        logging.info('exiting...')
        self.is_closing = True
    def try_exit(self):
        if self.is_closing:
            # clean up here
            tornado.ioloop.IOLoop.instance().stop()
            logging.info('exit success')
application = MyApplication([
    (r"/", MainHandler),
if __name__ == "__main__":
    tornado.options.parse_command_line()
    signal.signal(signal.SIGINT, application.signal_handler)
    application.listen(8888)
    tornado.ioloop.PeriodicCallback(application.try_exit, 100).start()
    tornado.ioloop.IOLoop.instance().start()

Output:

$ python test.py 
[I 181209 22:13:43 web:2162] 200 GET / (127.0.0.1) 0.92ms
^C[I 181209 22:13:45 test:21] exiting...
[I 181209 22:13:45 test:28] exit success
    tornado.ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
    tornado.ioloop.IOLoop.instance().stop()

Obviously, this is a less safe way.

UPDATE

Edited the code to remove use of global.

Thanks for reply. Your code is perfect. I am using tornado httpserver.When I press ctrl+c then it is take long time for kill the server. Any ideas. – dhana Jun 14 '13 at 10:56 You probably have some blocking task which has to be ended first before try_exit() callback is called. You can try to use tornado.ioloop.IOLoop.instance().stop() directly in signal handler but it seems much less secure for me. If you want to break infinite loop brutally in the middle of processing it will be hard to avoid error messages. – Nykakin Jun 14 '13 at 11:22 The original solution (handling signal.SIGINT) works great for me on Windows, but the "UPDATE" to your answer (simply catching KeyboardInterrupt) does not. Ctrl+C on Windows will not generate the KeyboardInterrupt and some people (like me, with a compact keyboard) don't have a CTRL+Pause Break on their keyboard. – Myk Willis Jan 20 '15 at 19:04 I'm not an expert in python but the use of a global variable in a scripting language is maybe a bad idea... why you don't do def signal_handler(signum, frame): tornado.ioloop.IOLoop.instance().stop() directly ? signals are events, you don't need a flag... anyway, none of the solutions work for me (Boot2Docker on Windows) – DestyNova Aug 4 '15 at 12:06 try: tornado.ioloop.IOLoop.instance().start() except KeyboardInterrupt: tornado.ioloop.IOLoop.instance().stop() does not work for me. – Josh Usre May 9 '17 at 19:41

You can simply stop the Tornado ioloop from a signal handler. It should be safe thanks to add_callback_from_signal() method, the event loop will exit nicely, finishing any eventually concurrently running task.

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()
                this should really be the accepted answer instead of polluting globals everywhere.
                    – cowbert
                Aug 7 '17 at 18:12
                do_stop() can be called from other places too. But indeed, it can be lambda.
                    – Ales Teska
                Aug 7 '17 at 18:34
                well in any case, due to the presence of bugs.python.org/issue18040 , nothing really works well on windows :(
                    – cowbert
                Aug 7 '17 at 18:57
                There is nothing like signals on Windows, you need to emulate that differently. Then having standalon do_stop() method can become handy.
                    – Ales Teska
                Aug 7 '17 at 19:43
                When you say 'CTRL+ instead of CTRL+C' do you actually mean Control and the 'plus' key? Because that does nothing for me
                    – puk
                Oct 17 '13 at 0:36
                I'm on Boot2Docker Windows and CTRL+C or CTRL+PAUSE kill the process, but the port is still in use...
                    – DestyNova
                Aug 4 '15 at 10:14
        

I'd say the cleanest, safest and most portable solution would be to put all closing and clean-up calls in a finally block instead of relying on KeyboardInterrupt exception:

import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")
application = tornado.web.Application([
    (r"/", MainHandler),
# .instance() is deprecated in Tornado 5
loop = tornado.ioloop.IOLoop.current()
if __name__ == "__main__":
        print("Starting server")
        application.listen(8888)
        loop.start()
    except KeyboardInterrupt:
    finally:
        loop.stop()       # might be redundant, the loop has already stopped
        loop.close(True)  # needed to close all open sockets
    print("Server shut down, exiting...")
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

site design / logo © 2020 Stack Exchange Inc; user contributions licensed under cc by-sa 4.0 with attribution required. rev 2020.1.28.35903