Max*_*Tet 5 python 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()
Run Code Online (Sandbox Code Playgroud)
如果运行程序并将SIGTERM发送给该进程,则将调用第16行中的print语句(停止事件循环),但程序不会终止,并且永远不会调用第13行中的print语句(事件循环已停止)。因此,似乎事件循环永远不会停止并且self._event_loop.run_forever()无限期地阻塞。
为什么是这样?
注意:程序的修改版本a.stop()可以按预期工作,而不是由信号处理程序调用,而是由具有延迟的单独线程调用。如何能有所作为怎么a.stop()叫?
而不是signal.signal()使用loop.add_signal_handler():
import asyncio
import signal
import os
class A:
def __init__(self):
self.loop = asyncio.new_event_loop()
self.loop.add_signal_handler(signal.SIGTERM, self.stop)
def stop(self):
print('stopping')
self.loop.stop()
def run(self, close=True):
print('starting loop')
try:
self.loop.run_forever()
print('loop stopped')
finally:
if close:
self.loop.close()
if __name__ == '__main__':
print("to stop run:\nkill -TERM {}".format(os.getpid()))
a = A()
a.run()
Run Code Online (Sandbox Code Playgroud)