Обработка ошибок Python: попробуйте / кроме / еще / наконец в 2026 году
Обработка ошибок отделяет «код, который работает на вашей машине», от «кода, который продолжает работать». Python try/Exception выглядит просто, но полная форма из четырех ключевых слов — try/Exception/else/finally – кодирует удивительное количество структур, которые пропускают большинство руководств.
В этом руководстве рассказывается: что на самом деле означает каждое ключевое слово, шесть шаблонов, которые вы встретите в каждой внутренней кодовой базе, когда определять свои собственные исключения, а также три антишаблона, которые позволяют ошибкам ускользнуть от ваших тестов.
Именно четыре ключевых слова
Предложение else используется недостаточно. В нем говорится: «Следующий бит зависит от успеха попытки, но я не хочу, чтобы он был защищен тем же исключением». Это подходящее место для продолжения счастливого пути — помещение его в try случайно перехватывает несвязанные исключения из ship(result).
Шесть шаблонов
1. Повторить попытку в случае временного сбоя
Правило: повторяйте попытку ТОЛЬКО при временных ошибках (сеть, тайм-аут, 429, 503). Никогда не повторяйте попытку с ValueError, KeyError, TypeError — это ошибки кода, и повторная попытка просто запускает ошибку три раза.
2. Охрана с помощью else
else гарантирует, что file был успешно открыт, И очистка области с with. Обратите внимание: process() может вызвать ValueError — оно будет распространяться вверх и НЕ будет перехватываться кроме FileNotFoundError.
3. Очистка с помощью finally (до появления with)
В современном коде вы должны использовать with db.connect() как conn: — with — это сахар вместо try/finally для обычного случая очистки. Используйте явное слово «finally» только в том случае, если ресурс не поддерживает протокол контекстного менеджера.
4. Повторный рейз с добавлением контекста
raise NewException(...) from e связывает исходное исключение с новым, так что обратная трассировка показывает ОБА. Никогда не пишите raise NewException(str(e)) — это отбрасывает исходную обратную трассировку.
5. Перехватывайте самое узкое исключение, которое только возможно
Правило: чем уже исключение, тем лучше. Если вы не знаете, какой «процесс» может вызвать, запустите его и выясните. кроме исключений: в 90% случаев является запахом кода.
6. raise внутри кроме — повторно поднять аккуратно
Простое raise сохраняет исходную обратную трассировку нетронутой. Никогда не используйте raise e (Python 3 умеет это делать, но простое raise — это идиоматическая форма).
Пользовательские исключения — когда оно того стоит
Определите свой собственный класс исключений, когда:
1. Вызывающие программы должны использовать исключение MyError: (т. е. у вас есть вызываемый API, и пользователям необходимо выполнять переход по типу сбоя).
2. Ваша библиотека/сервис вызывает несколько связанных ошибок, имеющих общий контекст.
Теперь вызывающие абоненты могут перехватывать широко («кроме PaymentError») или узко («кроме CardDeclinedError»). Структурированные атрибуты исключения (e.card_last4) позволяют обработчикам ошибок создавать полезный UX без анализа сообщений об исключении.
Антишаблон: определение специального исключения, которое возникает только один раз и никогда не перехватывается. Это просто raise ValueError("..."). Пользовательские исключения получают свой вес от того, что их перехватывают.
Три антипаттерна, скрывающие ошибки
Антипаттерн 1: Голое, кроме
Простое Exception перехватывает сигналы, которые должны выйти из программы (Ctrl-C, sys.exit, MemoryError). Никогда не пишите этого. Если вы действительно хотите перехватывать каждое нефатальное исключение, используйте «кроме исключений:» — оно ВСЕ ЕЩЕ перехватывает слишком много, но, по крайней мере, учитывает Ctrl-C.
Антипаттерн 2: Замалчивание без регистрации
Каждое пойманное исключение должно быть либо обработано (с определенным резервным вариантом), либо зарегистрировано. pass в исключении — это ошибка в замедленной съемке — кажется, что код работает, молча отбрасывая данные.
Антишаблон 3: кроме исключений: вокруг всего
Проблема: если stripe.charge прошел успешно, но send_receipt завершился неудачно, с клиента была снята плата, А вы проглотили ошибку. «Исключение» охватывает четыре различных режима отказа, и вы не сможете отличить их друг от друга.
Исправление: сузить область действия + разветвить область, кроме границы модуля.
Каждая попытка охватывает ОДНУ операцию. Каждый кроме знает, что делать с ЭТОЙ конкретной неудачей. Это обработка ошибок производственного уровня.
Хорошая обработка ошибок — это скорее дизайн, чем синтаксис. try/Exception/else/finally дает вам инструменты; дисциплина заключается в выборе правильного типа, кроме типа, максимально узкой области попыток и никогда не замалчивания ошибок, которые вы не понимаете.
Следующий шаг: курс «Основы» содержит 10 уроков по обработке исключений, пользовательским исключениям и оператору with — при этом настоящий Python работает в вашем браузере.