Чем asyncio.gather отличается от TaskGroup и как в них обрабатываются ошибки?
- Как запустить несколько корутин параллельно в asyncio?
- Что такое ExceptionGroup и except*?
Оба запускают корутины конкурентно. gather при первой ошибке пробрасывает её, но остальные задачи продолжают работать брошенными (если не return_exceptions=True). TaskGroup (3.11) — структурная конкурентность: ошибка в одной задаче отменяет остальные, блок ждёт завершения всех, ошибки приходят ExceptionGroup.
- except* разбирает ExceptionGroup по типам
- gather(return_exceptions=True) — исключения возвращаются в списке результатов
- TaskGroup не оставляет задач-сирот после выхода из блока
А ещё Для лимита параллелизма — Semaphore поверх любого из них
Подробно
gather:
results = await asyncio.gather(fetch(a), fetch(b), fetch(c))
Результаты — в порядке аргументов. Если fetch(b) упал, await gather бросит это исключение, но fetch(a) и fetch(c) не отменяются и продолжают работать в фоне; их ошибки могут потеряться («Task exception was never retrieved»).
С return_exceptions=True gather не бросает, а кладёт исключения в список результатов — удобно, когда нужно собрать всё, что получилось.
TaskGroup (Python 3.11):
async with asyncio.TaskGroup() as tg:
ta = tg.create_task(fetch(a))
tb = tg.create_task(fetch(b))
print(ta.result(), tb.result())
- выход из блока — только когда все задачи завершены;
- первая ошибка отменяет остальные задачи группы;
- все ошибки собираются в
ExceptionGroup.
Обработка ExceptionGroup:
try:
async with asyncio.TaskGroup() as tg: ...
except* TimeoutError as eg:
log.warning("таймауты: %s", eg.exceptions)
except* ValueError:
...
Выбор: новые проекты — TaskGroup: нет утечки задач и потерянных ошибок. gather — когда нужны частичные результаты при ошибках (return_exceptions=True) или код под Python < 3.11.
Что хотят услышать
- Поведение gather при ошибке.
- Структурная конкурентность TaskGroup.
- ExceptionGroup и except*.
Частые ошибки
- Считать, что gather отменяет остальные задачи при ошибке.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗gather при ошибке отменяет все остальные задачи, а TaskGroup дожидается их и возвращает ошибки списком
- ✓gather пробрасывает первую ошибку, не отменяя остальные; TaskGroup отменяет их и отдаёт ExceptionGroup
- ✗TaskGroup запускает задачи последовательно
- ✗Ошибки в TaskGroup молча игнорируются
Что спросят дальше
Разбор темы
- asyncio — корутины, задачи, отмена и блокирующий код
Как работают async и await, как запускать корутины одновременно, gather и TaskGroup, что делает блокирующий вызов в цикле событий, отмена и таймауты.
- Исключения и контекстные менеджеры
try, except, else и finally, свои исключения и цепочки raise from, with и контекстные менеджеры, ExceptionGroup.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.