Назвать ожидаемую неудачу
Строка из цифр может быть преобразована функцией int в целое число. Если строка содержит неподходящий текст, возникает ValueError. Это ожидаемая ситуация при обработке произвольного пользовательского ввода. Для неё можно вернуть понятное сообщение и попросить исправить значение. Но ошибка имени переменной или неверный вызов другой функции имеет другую природу. Общий except с пустым действием скрывает различия между этими случаями. Обработчик полезен, когда после исключения предусмотрено осмысленное действие. Отсутствие сообщения само по себе таким действием не является.
Сузить участок, который защищает try
Представим два шага: преобразовать текст, затем записать результат. Если оба находятся внутри большого try, обработчик ValueError может перехватить ошибку, возникшую уже при записи. Сообщение о неверном количестве тогда укажет на неправильную причину. Поэтому границу try стоит связать с конкретной операцией, исключение которой действительно ожидается. Блок else удобен для действий после успешного завершения try; исключение из самого else не обрабатывается предыдущими except этого же оператора. Это помогает отделить ошибочный ввод от последующей работы, у которой могут быть собственные причины сбоя.
Не превращать неизвестное в ноль
В учебном примере пользователь ввёл пять букв вместо количества. Если обработчик возвращает ноль, дальнейший расчёт может показать пустой заказ, хотя пользователь этого не выбирал. Ноль является допустимым числом, а не универсальной меткой неудачи. Лучше заранее определить отдельный исход ошибки: понятное сообщение, специальное значение или исключение для вызывающего кода. Выбор зависит от контракта функции. Важно, чтобы вызывающий код различал корректный ноль и невозможность получить число. Дополнительная проверка допустимого диапазона тоже необходима отдельно: успешно преобразованное отрицательное число может не подходить для количества товаров.
Завершение операции тоже требует ясности
finally предназначен для действий при выходе из конструкции, например освобождения ресурса, и выполняется при обычном ходе исполнения независимо от наличия обработанного исключения. Его не стоит использовать для объявления любого исхода успешным. Кроме того, return внутри finally способен перекрыть прежний результат или подавить исключение, усложнив поиск причины. Для начального разбора достаточно придерживаться простой схемы: ожидаемый сбой объясняется, неожиданный сохраняет диагностическую информацию, успех обозначается только после выполнения нужных шагов. Исключение нельзя считать исправленным только потому, что его перехватили. Проверять нужно итоговое состояние и возвращаемое значение.
Попробуйте на практике
На бумаге спроектируйте обработку количества товаров. Допустимы целые числа от нуля до ста; вход поступает как строка.
- Запишите четыре входа: текстовое представление числа семь, слово семь, текст отрицательного числа два и текст числа ноль.
- Определите, какие входы успешно преобразуются через int, а какой вызовет ValueError.
- После преобразования проверьте диапазон отдельно от обработки исключения.
- Для каждого случая укажите результат: допустимое количество, сообщение о формате или сообщение о диапазоне.
- Представьте, что последующая запись результата неожиданно завершилась ошибкой. Укажите, почему нельзя сообщать об успешном сохранении или обвинять формат входа без проверки.
Как проверить результат. Первый и четвёртый входы дают допустимые количества семь и ноль. Слово вызывает ошибку преобразования, отрицательное число проходит преобразование, но не проверку диапазона. Сбой записи остаётся отдельным исходом.
Частые вопросы
Можно ли перехватывать Exception?
Да, в обоснованных местах, например для регистрации неожиданного сбоя с последующим повторным возбуждением исключения. Проблема возникает при безусловном подавлении ошибки и продолжении работы будто ничего не произошло.
Нужно ли помещать весь код функции внутрь try?
Обычно полезнее ограничить try операциями, для которых предусмотрено конкретное восстановление. Это помогает не принять дефект следующего шага за уже известную проблему ввода.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.