Ожидание завершения asyncio.Task, распространение исключенийPython

Программы на Python
Anonymous
Ожидание завершения asyncio.Task, распространение исключений

Сообщение Anonymous »

Для рабочих нагрузок asyncio есть эта удобная функция, которая выполняет переданный список asyncio.Task до тех пор, пока
  • истечет время ожидания;
  • первая задача не вызовет исключение; или
  • все задачи выполняются успешно
Первые два случая всегда должны вызывать (повторное) возникновение исключения:

Код: Выделить всё

async def wait_and_reraise(futures: Sequence[asyncio.Task]) -> None:
try:
done, tasks_to_cancel = await asyncio.wait(
futures, timeout=5, return_when=asyncio.FIRST_EXCEPTION
)
except asyncio.CancelledError:
tasks_to_cancel = futures
raise
finally:
for task in tasks_to_cancel:
task.cancel()

for task in done:
if exc := task.exception():
raise exc
Затем я понял, что asyncio.wait() не будет вызывать вызов по тайм-ауту, поэтому вызывающая сторона предполагает, что задачи завершились успешно.
Из других ответов SO, сшитых вместе, следующее исправление (проверка длины выполненных задач, а также ожидание отмененных задач):

Код: Выделить всё

async def wait_and_reraise(tasks: Sequence[asyncio.Task]) -> None:
pending: None | Iterable[asyncio.Task] = None
try:
done, pending = await asyncio.wait(
tasks, timeout=5, return_when=asyncio.FIRST_EXCEPTION
)
except asyncio.CancelledError:
pending = tasks
raise
finally:
if pending:
for task in pending:
task.cancel()
await asyncio.gather(*pending, return_exceptions=True)
for task in done:
if exc := task.exception():
raise exc

if len(done) < len(tasks):
raise asyncio.TimeoutError("Tasks timed out before completion or exception.")
  • Разумная ли это реализация? Не могу не задаться вопросом, есть ли еще какие-то проблемы, о которых я не рассказываю.
  • Достаточно ли надежна логика отмены ожидающих задач? Зачем нужно ждать отмененных задач? Это значит, что ссылка на задачу не теряется и GC не добирается до нее до ее завершения (соответствующий пост)?

Вернуться в «Python»