try и except: ловим ошибку и не падаем
Первый запасной план: try держит рискованный код, except — что делать, если он упал. Прыжки, пропуски и try внутри цикла — на живом коде.
Редакция Питоники
Прошлый урок научил читать traceback: тип, место, сообщение. Но читать отчёт о падении приятно, когда падение — чужое. Настоящая сила в другом: сказать программе, что делать, если рискованная операция не удалась. Не падать, а переключиться на запасной план: подставить ноль, напечатать предупреждение, попросить данные ещё раз. Для этого в Python есть пара try и except — главный инструмент обработки исключений.
Запасной план: try и except
Схема проста. Слово try: открывает блок рискованного кода — строки с отступом, которые могут упасть. Слово except: — блок запасного плана: что делать, если в try случилось исключение. Вернёмся к разбору слова в число из первого урока, но теперь с планом Б:
try:
n = int('двенадцать')
print('Разобрали:', n)
except:
print('Не получилось разобрать число')
print('Программа работает дальше')
Не получилось разобрать число Программа работает дальше
Никакого traceback: программа не упала. Python начал выполнять try, дошёл до int('двенадцать'), получил ValueError — и вместо печати traceback перескочил в except. Там выполнился запасной план, а после него программа продолжилась по обычному пути: последняя строка отработала как ни в чём не бывало. Блок try выполняет рискованный код, блок except держит запасной план, который срабатывает вместо падения.
Если ошибки не случилось
Подсунем в тот же код число, которое разбирается без проблем:
try:
n = int('42')
print('Разобрали:', n)
except:
print('Запасной план')
print('Дальше идёт обычный код')
Разобрали: 42 Дальше идёт обычный код
Теперь в try всё прошло гладко, и блок except не выполнился ни разу: запасной план нужен только при аварии. Это важное свойство конструкции — except не запускается «на всякий случай», он строго реагирует на исключение. Поэтому в try пишут именно рискованный код, а не всю программу: лишний код в try — это лишние шансы случайно уронить его и зря запустить план Б.
Прыжок в except: остаток try пропускается
Исключение случается не в начале try, а в конкретной строке. Что происходит с остальными строками блока? Они пропускаются: прыжок в except происходит в момент сбоя, и выполнение в try не возвращается.
try:
print('первая строка try')
n = int('нет числа')
print('эта строка не выполнится')
except:
print('перешли в except')
print('после try')
первая строка try перешли в except после try
Первая строка try успела напечататься, вторая упала — и четвёртая строка блока осталась невыполненной навсегда. Python не возвращается в try после except: попытка сделана, план Б отработан, программа идёт дальше. Если в рискованном коде есть строки, которые должны выполниться даже при ошибке, им место не внутри try.
Ловим деление на ноль
ZeroDivisionError из первого урока — классический кандидат на обработку: сумма на ноль участников делится в любой статистике.
a = 10
b = 0
try:
print('Делим', a, 'на', b)
result = a / b
print('Результат:', result)
except:
print('Делить на ноль нельзя — считаем по-другому')
print('Конец программы')
Делим 10 на 0 Делить на ноль нельзя — считаем по-другому Конец программы
Печать «Делим 10 на 0» успела сработать — она была до аварийной строки. Само деление упало, и Python ушёл в except, не выполнив печать результата. Заметьте: программа не просто не упала — она дошла до конца. В первом уроке тот же код печатал traceback и обрывался.
try внутри цикла: спасти весь список
Самая рабочая схема новичка: список данных, где часть строк хорошая, а часть — мусор. Без обработки одна плохая строка уронит весь проход. try внутри цикла меняет правило: сбойная строка выпадает, остальные обрабатываются.
values = ['3', '5', 'кошка', '7']
for v in values:
try:
n = int(v)
print(v, '-> число', n)
except:
print(v, '-> не число')
3 -> число 3 5 -> число 5 кошка -> не число 7 -> число 7
Слово «кошка» не разобралось — и вместо падения всего отчёта мы получили одну честную строку «кошка -> не число». Цикл продолжился и разобрал семёрку. Этот приём — сердце обработки ошибок в данных, и к нему раздел вернётся ещё не раз: в уроке про несколько except мы уточним типы, а в уроке про as e начнём печатать текст ошибки в лог.
try и except — не для всего
У конструкции есть жёсткая граница: она ловит ошибки времени выполнения. Ошибки синтаксиса Python обнаруживает до запуска, когда ни try, ни except ещё не существуют.
try:
print('привет'
except:
print('не спасёт')
Вторая граница — минимальная комплектность. Одинокий try без запасного плана не имеет смысла, и Python проверяет это тоже — ещё до запуска:
try:
x = 1
Шпаргалка по поведению try
| Ситуация | Что делает программа |
|---|---|
| В try ошибка, except есть | Прыжок в except, дальше по обычному пути |
| В try ошибки нет | try выполняется целиком, except пропускается |
| Строка после аварии внутри try | Не выполняется: прыжок происходит в момент сбоя |
| Ошибка вне try | Обычный traceback: программа падает |
| SyntaxError в коде | Файл не запускается: try тут бессилен |
Остался последний кандидат — IndexError: обращение к списку по несуществующему номеру. Потренируемся ловить и его.
numbers = [10, 20, 30]
try:
print(numbers[5])
except:
print('Такого номера нет в списке')
print('Программа цела')
Такого номера нет в списке Программа цела
numbers = [10, 20, 30]
print(numbers[5])
print('эта строка не выполнится')
Traceback (most recent call last):
File "app.py", line 2, in <module>
print(numbers[5])
~~~~~~~^^^
IndexError: list index out of rangeДва блока с одними данными — два исхода. С try программа доходит до конца, без него обрывается на первой же строке с неверным индексом. Теперь у вас есть выбор для каждой рискованной операции: написать её как есть и получить traceback при сбое — или окружить try и except и решить, что делать при сбое. В следующем уроке мы сделаем обработчик точным: except ValueError ловит конкретный тип и не прячет чужие ошибки.
Сначала предскажи ответ в голове — это главный навык программиста.
try:
print('А')
x = int('9')
print('Б')
except:
print('В')
print('Г')
try:
print('А')
x = int('девять')
print('Б')
except:
print('В')
print('Г')
for text in ['2', 'x']:
try:
print(int(text) * 10)
except:
print('мимо')
print('финиш')
1. Что произойдёт с блоком except, если в try ошибок не было?
2. Внутри try упала вторая строка из пяти. Что будет с остальными строками try?
3. Обязательно ли после try писать except?
4. Спасёт ли try от SyntaxError — незакрытой скобки?
5. Зачем try кладут внутрь цикла for?
6. Какой код правильный по синтаксису?
7. Программа напечатала «Делим 10 на 0», затем строку except и «Конец программы». Упала ли она?
8. Почему длинный try на всю программу — плохая идея?
Дано value = 'семь'. Оберни разбор в try и except: при успехе напечатай «Получили число: N», при неудаче — «Не удалось разобрать: семь», а после try — строку «Готово». Программа не должна упасть.
Как работает try except в Python?
Python выполняет блок try строка за строкой. Если случилось исключение, выполнение перескакивает в except и после него программа продолжается. Если исключения не было, except пропускается целиком. Строки try после аварийной не выполняются.
Урок 3: except ValueError — конкретный типМожно ли писать except без указания типа ошибки?
Синтаксически можно: голый except ловит любые исключения. Но в настоящем коде так делать не рекомендуют — вместе с настоящей проблемой он прячет опечатки и баги. Лучше называть тип: except ValueError для разбора значений, except ZeroDivisionError для деления.
Что класть в блок try?
Только ту операцию, которой не доверяете: разбор строки в число, деление, обращение к словарю. Чем короче try, тем точнее видно, что именно упало. Весь остальной код пишется после except без отступа.
Выполнятся ли строки после аварийной внутри try?
Нет. Прыжок в except происходит в момент сбоя, и обратно в try программа не возвращается. Код, который должен выполниться при любом исходе, выносят за пределы try — или используют finally, о котором рассказано в уроке про else и finally.
Урок 6: else и finallyМожет ли try быть внутри цикла?
Да, и это самая рабочая схема обработки данных: for перебирает строки, try оборачивает разбор каждой. Одна плохая строка уходит в except, остальные обрабатываются. Цикл продолжается после сбоя — весь список не падает из-за одного элемента.
Понравился урок? Сошлитесь на него
«Блок try выполняет рискованный код, блок except держит запасной план, который срабатывает вместо падения.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Исключения · Урок 1
Что такое исключение: первая ошибка в программе
Первая ошибка в программе: читаем traceback за десять секунд — тип ошибки, место и сообщение. Разбираем четыре типовых падения на живом коде.
Исключения · Урок 3
except ValueError: ловим конкретный тип ошибки
Уточняем обработчик: except ValueError ловит только свой тип ошибок. Почему голый except прячет опечатки и как ValueError ведёт себя у int и list.remove.
Исключения · Урок 4
Несколько except: разные ошибки — разные реакции
Цепочка except-блоков: ValueError — один план, ZeroDivisionError — другой. Порядок обработчиков, правило одного обработчика и кортеж типов.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
aiogram · Урок 9
Обработка ошибок в телеграм-боте: try/except, лимиты и логи
Учим бот переживать ошибки: try/except в хендлерах, лимиты Telegram с RetryAfter, модуль logging вместо print и перезапуск polling после падения.
обработка ошибок pythontry except python
Flask · Урок 11
Обработка ошибок во Flask: свои страницы 404 и 500
Одиннадцатый урок курса Flask: гость опечатался в адресе — и видит английскую заглушку без вашего меню. Учимся отдавать свои страницы 404 и 500 через @app.errorhandler, честно отвечать abort(404), когда записи нет, и проверять статусы через test_client.
flask обработка ошибок 404flask обработка исключений
Исключения · Урок 15
except Exception в Python: когда ловить всё и чем это грозит
Одна строка вместо перечня типов: except Exception ловит почти всё. Разбираем слепую зону перехвата, спрятанные баги и место, где широкая сетка уместна по-настоящему.
except exception pythonpython except exception