TGViewer
About Python [ru] About Python [ru] @python_tesst · 6.44K subscribers
Post #2756 404
⁣ExceptionGroup + Rich: как читать production traceback, когда падает не одно, а всё сразу

В production с asyncio или concurrent.futures стандартный traceback — это простыня, где последняя ошибка съедает все предыдущие. Вы видите только финал, а корень теряется. Особенно когда цепочка задач падает каждая со своим исключением, и вы не понимаете, что именно пошло не так и в каком порядке.

Проблема: traceback теряет контекст
Обычный traceback показывает только последнюю ошибку. Если у вас 10 задач и 5 упали с разными исключениями, вы получите только одно. Всё, что было до него, исчезает. Для asyncio.gather() или concurrent.futures это катастрофа: ошибка может быть не в последней задаче, а в первой, но её уже нет.

Решение: ExceptionGroup + Rich
Python 3.11 ввёл ExceptionGroup (PEP 654). Он группирует несколько исключений в одно, сохраняя полную структуру. Но сам по себе он неудобен для чтения. Rich решает это: он рендерит ExceptionGroup с цветами, вложенностью и локальными переменными для каждого исключения.

import asyncio
from rich.console import Console
from rich.traceback import install

install(show_locals=True)
console = Console()

async def task(id: int):
if id % 2 == 0:
raise ValueError(f"Even ID: {id}")
raise RuntimeError(f"Odd ID: {id}")

async def run():
errors = []
for i in range(4):
try:
await task(i)
except Exception as e:
errors.append(e)
if errors:
raise ExceptionGroup("Tasks failed", errors)

try:
asyncio.run(run())
except ExceptionGroup as eg:
console.print_exception(show_locals=True)


Что даёт такой подход в production
Три вещи, которые превращают stack trace из мусора в actionable insight:
* визуальная группировка: видно, какие ошибки относятся к одному запуску задач, а не размазаны по логу;
* локализация: Rich показывает локальные переменные на момент падения для каждого исключения — не нужно гадать, какое значение было у id;
* иерархия: если у вас вложенные ExceptionGroup, структура не теряется, и вы видите, где какая ошибка возникла.

Практический совет
Добавляйте в ExceptionGroup метаданные — время, id запроса, контекст выполнения. Тогда по логу сразу понятно, что именно сломалось и при каких условиях. Для Python < 3.11 используйте пакет exceptiongroup — он работает аналогично и ставится через pip.

Типичная ошибка
Пытаться обработать ExceptionGroup как обычное исключение через except Exception. Это сломает логику: вы потеряете все вложенные ошибки. Используйте except* (PEP 654) или явно перехватывайте ExceptionGroup.

Trade-off
ExceptionGroup добавляет накладные расходы на сбор ошибок, если их много. Используйте только для задач, где ошибки реально могут быть множественными (batch processing, фоновые воркеры), а не для одиночных вызовов.

Вывод:
ExceptionGroup вместе с Rich превращает traceback из хаоса в структурированную карту боя, где каждая ошибка видна со своим контекстом, и вы не гадаете, что сломалось на самом деле.
  • 👍 1
More from @python_tesst
  1. Sep 29, 2026Claude Sonnet 5.5 — уже не слив, релиз официально состоялся Прайс не трогали: $2 за миллио…
  2. Sep 29, 2026Post #3194
  3. Sep 29, 2026Дженсен Хуанг выкатил NVIDIA Open Agent Safety Platform — и притащил с собой 100+ партнеро…
  4. Sep 29, 2026Стикмену теперь под силу снести любой сайт. Чувак под это навайбкодил целую игруху: грузиш…
  5. Sep 28, 2026Post #3191
  6. Sep 27, 2026OpenAI метит в подписку за 500 баксов Что там в описании тарифа? Пока что от ChatGPT Pro о…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →