Как остановить веб-сервер торнадо с помощью ctrl + c?
Я новичок в веб-сервере торнадо. Когда я запускаю веб-сервер торнадо, используя python main_tornado.py Он работает. См. Ниже код.
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()
Когда я останавливаю сервер с помощью CTRL + C, он дает следующую ошибку.
^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
Пожалуйста, решите мою проблему. Спасибо..
Ответы
Ответ 1
Вы можете остановить основной цикл Tornado с tornado.ioloop.IOLoop.instance().stop()
. Чтобы этот метод вызывался после передачи сигнала с помощью Ctrl + C, вы можете периодически проверять глобальный флаг, чтобы проверить, должен ли основной цикл завершиться, и зарегистрировать обработчик для сигнала SIGINT, который изменит значение этого флага:
#!/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()
Выход:
$ 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 долго опрашивал запросы на это простое решение:
try:
tornado.ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
tornado.ioloop.IOLoop.instance().stop()
Очевидно, это менее безопасный способ.
ОБНОВИТЬ
Отредактировал код, чтобы убрать использование global
.
Ответ 2
Вы можете просто остановить Tornado ioloop от обработчика сигнала. Это должно быть безопасно благодаря методу add_callback_from_signal(), цикл событий будет прекрасным, заканчивая любую в конечном итоге одновременно выполняющуюся задачу.
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
Код в порядке. CTRL + C генерирует KeyboardInterrupt. Чтобы остановить сервер, вы можете использовать CTRL + Pause Break (в окнах) вместо CTRL + C. В linux CTRL + C также генерируется KeyboardInterrupt. Если вы будете использовать CTRL + Z, программа остановится, но порт занят.
Ответ 4
Я бы сказал, что самым чистым, безопасным и наиболее переносимым решением было бы поместить все закрывающие и очищающие вызовы в блок finally
а не полагаться на исключение KeyboardInterrupt
:
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...")