Есть несколько способов подойти к этому, но центральная идея состоит в том, что в asyncio, в отличие от многопоточной обработки c, легко ожидать нескольких вещей одновременно.
Например, вы можете ждать queue.join()
и рабочие задачи, в зависимости от того, что выполнено первым. Так как работники не заканчивают нормально (вы отменяете их позже), работник, выполняющий завершение, означает, что он поднял.
# convert queue.join() to a full-fledged task, so we can test
# whether it's done
queue_complete = asyncio.create_task(queue.join())
# wait for the queue to complete or one of the workers to exit
await asyncio.wait([queue_complete, *tasks], return_when=asyncio.FIRST_COMPLETED)
if not queue_complete.done():
# If the queue hasn't completed, it means one of the workers has
# raised - find it and propagate the exception. You can also
# use t.exception() to get the exception object. Canceling other
# tasks is another possibility.
for t in tasks:
if t.done():
t.result() # this will raise