У меня есть программа-демон с кучей asyncio.coroutine
-х, которые могут быть подведены к чему-то вроде этогождать asyncio сопрограмм закончить в определенном порядке
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
потому coroutine1
могут возникнуть проблемы делают свои вещи, если coroutine2
не делает его вещи больше.
Мой вопрос здесь как я убеждаюсь coroutine1
заканчивается перед тем coroutine2
?