【发布时间】:2017-05-29 17:24:39
【问题描述】:
我有一个包含一堆 asyncio.coroutine 的守护程序,可以总结为类似这样的内容
import asyncio
import signal
class Daemon:
def __init__(self, loop=asyncio.get_event_loop()):
self.loop = loop
self.running = False
self.tasks = {
'coroutine1': asyncio.ensure_future(self.coroutine1()),
'coroutine2': asyncio.ensure_future(self.coroutine2()),
}
def run(self):
self.running = True
for task in self.tasks.values():
task.add_done_callback(self.task_done_callback)
# gracefuly close everything when SIGINT (could be ^C) is received
self.loop.add_signal_handler(signal.SIGINT, self.close)
self.loop.run_forever()
def close(self):
self.running = False
self.loop.run_until_complete(self.tasks['coroutine1'])
self.loop.run_until_complete(self.tasks['coroutine2'])
def task_done_callback(self, future):
for task in self.tasks.values():
if not task.done():
return
self.loop.stop()
@asyncio.coroutine
def coroutine1(self):
while self.running:
print('coroutine1: do stuff')
yield from asyncio.sleep(1)
@asyncio.coroutine
def coroutine2(self):
while self.running:
print('coroutine2: do some other stuff')
yield from asyncio.sleep(3)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
daemon = Daemon(loop)
daemon.run()
loop.close()
当程序接收到SIGINT 时,守护程序会正常关闭。当这种情况发生时,close() 方法被触发,该方法负责通知所有正在运行的任务它们应该完成工作并停止。这只需将running 设置为False 即可。每当一个任务完成时,Daemon.task_done_callback 就会被触发。它检查是否所有任务都已完成,如果是,则停止循环。
这里的问题是close() 方法不起作用。那是因为我在循环已经运行时调用了loop.run_until_complete(通过run_forever)。这将产生一个RuntimeError('This event loop is already running')。
重要的是:coroutine1 需要在 coroutine2 之前完成,因为如果 coroutine2 不再做它的事情,coroutine1 可能会遇到问题。
我的问题是我如何确保coroutine1 在coroutine2 之前完成?
【问题讨论】:
标签: python concurrency python-asyncio coroutine