15

我是龙卷风网络服务器的新手。当我使用 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

请解决我的问题。谢谢..

4

4 回答 4

29

你可以用 . 停止 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.

于 2013-06-14T09:23:18.857 回答
8

您可以简单地从信号处理程序中停止 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()
于 2017-05-13T00:11:07.157 回答
3

代码没问题。CTRL+C 生成键盘中断。要停止服务器,您可以使用 CTRL+Pause Break(在 Windows 上)而不是 CTRL+C。在 linux 上 CTRL+C 也会生成 KeyboardInterrupt 。如果您将使用 CTRL+Z 程序将停止但端口变得繁忙。

于 2013-06-14T17:27:43.943 回答
0

我想说最干净、最安全和最便携的解决方案是将所有关闭和清理调用放在一个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...")
于 2018-07-26T23:39:58.573 回答