Уместно ли использовать pattern matching для обработки исключений в глобальном exception handler в Python
Что проверяют
Отличаете ли вы диспетчеризацию по типу исключения, которая в языке уже есть, от разбора содержимого ошибки, и не тянете ли новый синтаксис туда, где он ничего не упрощает. Вопрос с подвохом: ожидаемый ответ звучит как «иногда», и интересна именно граница.
Как отвечать
Начните с того, что try и except уже умеют главное: выбирают ветку по классу исключения с учётом наследования. Если решение зависит только от типа, match не добавляет ничего, кроме лишнего уровня вложенности.
match оправдан, когда тип один, а поведение зависит от содержимого: ошибка драйвера базы со своим кодом внутри, ошибка внешнего сервиса со статусом ответа.
match exc:
case ApiError(status=404):
return not_found()
case ApiError(status=int() as code) if code >= 500:
return retry_later()
case ValueError() | TypeError():
return bad_request()
case _:
raiseСкобки после имени класса обязательны, это ключевой момент синтаксиса. Дальше скажите, как устроен глобальный обработчик в вашем стеке: в популярных веб-фреймворках регистрируется таблица обработчиков по типу исключения, и она уже решает задачу выбора ветки, а match живёт внутри одного такого обработчика.
Хорошее завершение: собственная иерархия доменных исключений полезнее любого синтаксиса. Когда есть базовый класс приложения и наследники с полями, обработчику хватает одного except, а разбор превращается в чтение атрибутов и маппинг на код ответа.
Где спотыкаются
Пишут case ValueError: без скобок. Это не проверка класса, а связывание имени: в переменную попадает что угодно, ветка срабатывает всегда, следующие не выполняются никогда. Ошибка тихая, тестами на счастливый путь не ловится.
Второе: превращают глобальный обработчик в место, где исключение гасится. Логировать надо вместе с трассировкой, а при повторном возбуждении сохранять причину через raise ... from, иначе исходное место падения теряется и разбор инцидента упирается в пустоту.
Третье: забывают про группы исключений. Когда параллельные задачи падают пачкой, наружу приходит группа, и обычная ветка по типу её не разберёт, для этого есть отдельная форма except*.