优雅地停止龙卷风ioLoop

时间:2018-04-17 09:04:10

标签: python tornado sigterm ioloop

我使用龙卷风的ioloop有这个异步工作者功能。 我正试图在 Ctrl + C 上优雅地关闭循环但是出现以下错误

  

tornado.ioloop.TimeoutError:无秒后操作超时

我知道我能抓住它,但我确实希望以优雅的方式完成这个过程,我怎样才能实现呢?

#!/usr/bin/env python
import time
import signal
import random

from tornado import gen, ioloop, queues

concurrency = 10

def sig_exit(signum, frame):
    ioloop.IOLoop.current().add_callback_from_signal(shutdown)

def shutdown():
    print('Will shutdown in few seconds ...')
    io_loop = ioloop.IOLoop.current()

    deadline = time.time() + 3

    def stop_loop():
        now = time.time()
        if now < deadline and (io_loop._callbacks or io_loop._timeouts):
            io_loop.add_timeout(now + 1, stop_loop)
        else:
            io_loop.stop()
            print('Shutdown')

    stop_loop()

@gen.coroutine
def main():
    q = queues.Queue()
    q.put(1)

    @gen.coroutine
    def do_stuff():
        print("doing stuff")
        yield gen.Task(ioloop.IOLoop.instance().add_timeout, time.time() + random.randint(1, 5))
        print("done doing stuff")

    @gen.coroutine
    def worker():
        while True:
            yield do_stuff()

    for _ in range(concurrency):
        worker()

    yield q.join()


if __name__ == '__main__':
    signal.signal(signal.SIGTERM, sig_exit)
    signal.signal(signal.SIGINT, sig_exit)

    io_loop = ioloop.IOLoop.instance()
    io_loop.run_sync(main)

2 个答案:

答案 0 :(得分:0)

如果您使用run_sync,则无法再致电IOLoop.stop - run_sync现在负责此事。因此,如果您希望使此关闭“优雅”(而不是仅在您现在调用stop()并使用堆栈跟踪退出时引发KeyboardInterrupt),则需要更改传递给{{1}的协同程序所以它退出了。

一种可能的解决方案是run_sync

tornado.locks.Event

答案 1 :(得分:0)

async def main():
    tornado.options.parse_command_line()
    ...
    app = Application(db)
    app.listen(options.port)
        
    shutdown_event = tornado.locks.Event()
    def shutdown( signum, frame ):
        print("shutdown  database !!!!")
        db.close()
        shutdown_event.set()


    signal.signal(signal.SIGTERM, shutdown)
    signal.signal(signal.SIGINT, shutdown)

    await shutdown_event.wait()
    print("\n\nshutdown -h now")

if __name__ == "__main__":
    tornado.ioloop.IOLoop.current().run_sync(main)