Что такое обработка исключений?
Обработка исключений это способ, которым программа реагирует на ошибки, возникающие во время её работы. Код, который может дать сбой, помещают в защищённый блок, например try, и когда возникает ошибка, управление переходит к обработчику, например except или catch, а программа не падает.
Обновлено 24 сентября 2026 г.
Программа, которая спрашивает у людей возраст, рано или поздно получит «twenty» вместо 20. Преобразование такого текста приводит к ошибке времени выполнения: int("twenty") выбрасывает ValueError, и если на этот случай нет плана, программа останавливается. Обработка исключений и есть такой план. Ты отмечаешь код, который может дать сбой, и пишешь код, который выполнится, если сбой произойдёт.
Next year you will be 35
Not a number: twenty
Next year you will be 20
Done
О плохом ответе сообщается, и цикл переходит к следующему. Без try программа вывела бы одну строку, а за ней traceback.
Как работает обработка исключений
- Код внутри
tryвыполняется как обычно. - Операция не удаётся, и среда выполнения выбрасывает исключение: объект с типом (
ValueError) и сообщением (invalid literal for int() with base 10: 'twenty'). - Блок
tryостанавливается на этой строке. Оставшиеся его строки пропускаются, поэтому для «twenty» не выводится «Next year you will be». - Среда выполнения сравнивает тип исключения с каждым блоком
exceptсверху вниз и выполняет первый подходящий. - Когда обработчик заканчивает работу, программа продолжается с первой строки после всей инструкции
try. - Если ни один блок не подошёл, исключение покидает текущую функцию, и поиск продолжается в функции, которая её вызвала, затем в той, что вызвала её. Это называется раскруткой стека вызовов. Если поиск доходит до верха программы и ничего не находит, программа завершается с traceback.
Из шага 6 следует, что обработчик не обязан находиться в той функции, где происходит ошибка. Здесь сбой случается на глубине двух вызовов, и обработчик внизу всё равно его перехватывает:
parsing 4.50
parsing free
Could not add the prices: could not convert string to float: 'free'
float("free") не сработал внутри parse_price. Ни у parse_price, ни у total обработчика не было, поэтому обе функции были прерваны, и «3.20» так и не разобрано. Это главный выбор, который даёт обработка исключений: обрабатывать ошибку там, где ты знаешь, что с ней делать, а это часто далеко от места, где она произошла.
try, except, else и finally
У инструкции try в Python есть ещё две необязательные части. else выполняется, только если блок try завершился без исключения. finally выполняется в любом случае: после успеха, после обработанного исключения и даже когда функция возвращает значение изнутри try.
no error
finally runs either way
2.0
b was zero
finally runs either way
None
В finally помещают освобождение ресурсов: закрытие файла, снятие блокировки, закрытие соединения с базой данных. В Python инструкция with делает это для файлов автоматически, и для них обычно выбирают её.
Как выбрасывать свои исключения
Исключения нужны не только для ошибок, которые обнаруживает сам язык. Когда твоя функция получает входные данные, с которыми не может работать, она может выбросить исключение, чтобы отказаться, а вызывающий код решит, что делать дальше. Небольшой собственный класс исключения даёт ошибке имя, которое её описывает.
70
Refused: cannot take 250, balance is 100
В Python для этого используется raise. В Java, C++ и JavaScript то же самое делает throw.
Обработка исключений в других языках
| Язык | Ключевые слова | Что стоит знать |
|---|---|---|
| Python | try, except, else, finally, raise | Каждое исключение это объект, унаследованный от BaseException |
| Java | try, catch, finally, throw, throws | Проверяемые исключения, например IOException, нужно перехватить или объявить через throws |
| C++ | try, catch, throw | Нет finally; ресурсы освобождают деструкторы при раскрутке стека |
| JavaScript | try, catch, finally, throw | Ошибки в async коде перехватывают через try вокруг await |
| C | нет | Функции возвращают код ошибки, и многие устанавливают errno |
| Go | нет для обычных ошибок | Функции возвращают значение error, которое проверяет вызывающий код |
Тот же пример с разбором на Java выглядит так:
try {
int age = Integer.parseInt("twenty");
System.out.println(age + 1);
} catch (NumberFormatException e) {
System.out.println("Not a number: " + e.getMessage());
} finally {
System.out.println("done");
}
Java делит исключения на две группы. Проверяемые исключения, например IOException, описывают проблемы вне контроля программы, и компилятор отказывается собирать код, который их не перехватывает и не объявляет. Непроверяемые исключения, подклассы RuntimeException, например NullPointerException, обычно означают баг, и компилятор не заставляет их обрабатывать.
Частые ошибки
- Перехват всего подряд. Голый
except:в Python перехватывает иKeyboardInterrupt, поэтому Ctrl+C перестаёт работать, аexcept Exception:ловит баги, которые ты никогда не планировал. Перехватывай конкретный тип, который знаешь, как обработать. - Проглатывание ошибки.
except ValueError: passпрячет проблему. Как минимум выведи или запиши в лог, что пошло не так. - Слишком большой блок
try. Оборачивай только те строки, которые могут выбросить перехватываемое исключение, чтобы посторонняя ошибка не была обработана по случайности. - Перехват багов вместо исправления.
IndexErrorиз цикла, который делает на один шаг больше, это ошибка в коде. Её обработка сохраняет неправильный код в живых. - Ожидание, что
catchпредотвратит падение в C или C++. Ошибка сегментации это сигнал операционной системы, а не исключение, и в Linux и macOScatch (...)в C++ её никогда не увидит.
Что читать дальше
Ошибки, на которые реагирует обработка исключений, описаны на странице про ошибку времени выполнения, а падение, которое она перехватить не может, на странице про ошибку сегментации. Полный синтаксис есть в руководствах по исключениям в Python, try и catch в Java, исключениям в C++ и try и catch в JavaScript. В курсе Java и курсе Python они отрабатываются на настоящих упражнениях.
Часто задаваемые вопросы
Какие 5 ключевых слов используются для обработки исключений в Java?
try, catch, finally, throw и throws. try отмечает код, за которым нужно следить, catch обрабатывает конкретный тип исключения, а finally выполняет завершающий код независимо от того, было ли исключение. throw выбрасывает исключение, а throws в сигнатуре метода объявляет, какие проверяемые исключения метод может передать вызывающему коду.Как устроена обработка исключений в C++?
try, catch и throw. Выбросить можно значение любого типа, но по соглашению выбрасывают объект, производный от std::exception, например std::runtime_error, и перехватывают его по ссылке: catch (const std::exception& e). В C++ нет finally; освобождение ресурсов происходит в деструкторах, которые вызываются автоматически при раскрутке стека.Чем ошибка отличается от исключения?
Exception охватывает проблемы, которые программа может разумно обработать, а Error, например OutOfMemoryError или StackOverflowError, сигнализирует о сбое JVM, который программе обычно не стоит пытаться перехватывать. В Python ValueError и ZeroDivisionError оба исключения, несмотря на названия.Чем throw отличается от throws в Java?
throw это инструкция, которая выбрасывает одно исключение в этом месте: throw new IllegalArgumentException("negative age");. throws это часть объявления метода, где перечислены проверяемые исключения, которые метод может передать вызывающему коду: void load() throws IOException. После этого компилятор заставляет каждый вызывающий код либо перехватить это исключение, либо тоже его объявить.Замедляет ли обработка исключений код?
try в большинстве современных языков почти бесплатен. Начиная с Python 3.11, try практически ничего не стоит, если исключение не выброшено, а основные компиляторы C++ не добавляют затрат во время выполнения на пути, где ничего не выбрасывается. Выбросить и перехватить исключение намного медленнее, чем проверить if, поэтому в циклах, где важна скорость, проверяй частые случаи явно, а не полагайся на исключения.