获取系统信号时的asyncio清理

时间:2018-04-18 14:06:05

标签: python python-3.x python-asyncio aiohttp

我有一个在事件循环中永远运行的监视器,我想在接收sigint信号时正确关闭它( Ctrl + C )。 请考虑以下示例

class Scheduler(object):
    def __init__(self, tasks=None, interval=1):
        self.tasks = tasks or []
        self.interval = interval

    async def run_forever(self):
        while True:
            await self.run_once()
            print('Waiting %s seconds to make next update...' %
                  self.interval)
            await asyncio.sleep(self.interval)

    async def run_once(self):
        await asyncio.gather(*self.tasks)

    async def cleanup(self):
        print('Cleaning up resources...')


async def run(scheduler):
    try:
        await scheduler.run_forever()
    finally:
        await scheduler.cleanup()

def main():
    loop = asyncio.get_event_loop()
    scheduler = Scheduler()
    loop.run_until_complete(run(scheduler))


if __name__ == '__main__':
    main()

但它并没有在finally子句

中调用清理函数
DEBUG:asyncio:Using selector: EpollSelector
Waiting 1 seconds to make next update...
Waiting 1 seconds to make next update...
^CTraceback (most recent call last):
  File "shce.py", line 60, in <module>
    main()
  File "shce.py", line 50, in main
    loop.run_until_complete(run(scheduler))
  File "/usr/local/lib/python3.6/asyncio/base_events.py", line 454, in run_until_complete
    self.run_forever()
  File "/usr/local/lib/python3.6/asyncio/base_events.py", line 421, in run_forever
    self._run_once()
  File "/usr/local/lib/python3.6/asyncio/base_events.py", line 1395, in _run_once
    event_list = self._selector.select(timeout)
  File "/usr/local/lib/python3.6/selectors.py", line 445, in select
    fd_event_list = self._epoll.poll(timeout, max_ev)
KeyboardInterrupt

但下面的代码可以正常使用

def main():
    loop = asyncio.get_event_loop()
    scheduler = Scheduler()
    try:
        loop.run_until_complete(scheduler.run_forever())
    except KeyboardInerrupt:
        print('Soo god')
    finally:
        loop.run_until_complete(scheduler.cleanup())

第一个代码示例中缺少什么,它不想调用清理代码,它与第二个代码示例有什么不同?

1 个答案:

答案 0 :(得分:1)

两个片段都是平等的,并且做同样的工作。

从我的角度来看,第二个看起来更优雅。