How to stop the tornado web server with ctrl+c?

后端 未结 4 1462
北荒
北荒 2021-02-05 13:21

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
         


        
相关标签:
4条回答
  • 2021-02-05 13:35

    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()
    
    0 讨论(0)
  • 2021-02-05 13:44

    The code is OK. The CTRL+C generates KeyboardInterrupt. To stop the server you can use CTRL+Pause Break(on windows) instead of CTRL+C. On linux CTRL+C also generates the KeyboardInterrupt also. If you will use CTRL+Z program will stop but port gets busy.

    0 讨论(0)
  • 2021-02-05 13:47

    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
    

    UPDATE

    I've just saw in question Tornado long polling requests this simple solution:

    try:
        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.

    0 讨论(0)
  • 2021-02-05 13:54

    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__":
        try:
            print("Starting server")
            application.listen(8888)
            loop.start()
        except KeyboardInterrupt:
            pass
        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...")
    
    0 讨论(0)
提交回复
热议问题