2
以下最小程序会重现此问题。通过SIGTERM间接停止python asyncio事件循环没有任何效果
import asyncio
import signal
class A:
def __init__(self):
self._event_loop = asyncio.new_event_loop()
def run(self):
print('starting event loop')
self._event_loop.run_forever()
print('event loop has stopped')
def stop(self):
print('stopping event loop')
self._event_loop.stop()
if __name__ == '__main__':
a = A()
def handle_term(*args):
a.stop()
signal.signal(signal.SIGTERM, handle_term)
a.run()
如果你运行该程序,并发送一个SIGTERM的过程,在第16行的打印语句(停止事件循环)被调用,但PROGRAMM不会终止,并在第13行的打印语句(事件循环有停止)从未被调用。所以看起来,事件循环从未停止,并且无限期地阻止了self._event_loop.run_forever()
。
这是为什么?
注意:该程序的修改版本,其中a.stop()
未由信号处理程序调用,而是由具有延迟的单独线程调用,如预期的那样工作。如何调用a.stop()
?
这就是我如何解决它现在。但我不喜欢它。它将在A类的事件循环内运行的逻辑与如何停止的逻辑相耦合。从结构上来说,将这两者分离得更干净,并让A的事件循环从A之外停止。 另外:我仍然很好奇为什么我的示例不起作用。据我所知,它应该工作,对吧? –
您可以使用'faulthandler.dump_traceback()'来查看您的程序卡在'select()'中。 Unix需要使用['signal.set_wakeup_fd()'](https://docs.python.org/3.4/library/signal.html#signal.set_wakeup_fd)唤醒poll/select。 – Udi