import asyncio # Новое в Python 3.11. async with asyncio.TaskGroup() as tg: task1 = tg.create_task(some_coro(...)) ...
TaskGroup
.Класс TaskGroup()
(добавлен в Python 3.11.) модуля asyncio
представляет собой асинхронный менеджер контекста, содержащий группу задач.
Группы задач asyncio.TaskGroup()
сочетают в себе API создания задач с удобным и надежным способом ожидания завершения всех задач в группе.
Отдельные задачи можно добавлять в группу с помощью метода TaskGroup.create_task()
. Все задачи ожидаются при выходе из менеджера контекста.
TaskGroup.create_task(coro, *, name=None, context=None)
:Метод TaskGroup.create_task()
создает задачу в этой группе задач. Принимаемые аргументы и поведение этого метода совпадает с описанием asyncio.create_task()
.
Пример:
async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task(some_coro(...)) task2 = tg.create_task(another_coro(...)) print("Обе задачи уже выполнены.")
Оператор async with
будет ожидать завершения всех задач в группе. Во время ожидания, в группу, все еще могут быть добавлены новые задачи (например, путем передачи экземпляра tg
в одну из сопрограмм и вызова tg.create_task()
в этой сопрограмме). После завершения последней задачи и выхода из блока async with
в группу нельзя добавлять новые задачи.
При первом сбое любой из задач, принадлежащих группе tg
, с исключением asyncio.CancelledError
, оставшиеся задачи в группе отменяются. После этого в группу нельзя будет добавить больше задач. В этот момент, если тело асинхронного оператора with
все еще активно (т. е. __aexit__()
еще не вызывалась), то задача, непосредственно содержащая асинхронный оператор with
, также отменяется. Полученный asyncio.CancelledError
прервет ожидание, но не выйдет из содержащего оператора async with
.
После завершения всех задач, если какие-либо задачи завершились сбоем с исключением, отличным от asyncio.CancelledError
, эти исключения объединяются в ExceptionGroup
или BaseExceptionGroup
(соответственно; смотрите их документацию), которая затем вызывается.
Два базовых исключения обрабатываются особым образом: если какая-либо задача завершается с ошибкой с помощью KeyboardInterrupt
или SystemExit
, то группа задач по-прежнему отменяет оставшиеся задачи и ожидает их, но затем повторно вызывается первоначальная KeyboardInterrupt
или SystemExit
вместо ExceptionGroup
или BaseExceptionGroup
.
Если тело оператора async with
завершается с исключением (поэтому __aexit__()
вызывается с набором исключений), то ситуация обрабатывается так же, как если бы одна из задач не удалась: оставшиеся задачи отменяются, а затем ожидаются (т.е. исключения отмены НЕ группируются в группу исключений и вызываются). Исключение, переданное в __aexit__()
, если оно не является asyncio.CancelledError
, также включается в группу исключений. Для KeyboardInterrupt
и SystemExit
делается тот же особый случай, что и в предыдущем абзаце.