Как правильно обрабатывать исключения в блоках try-except в Python?

Я пишу на Python уже пару лет, но всё ещё не уверен, нужно ли ловить конкретные исключения или можно использовать широкий except. В моём коде сейчас много универсальных обработчиков исключений, и я не знаю, это плохая практика или для небольших проектов это нормально.

2 ответа

★ Лучший ответ

Что ты там на самом деле делаешь с этими исключениями, когда они возникают - логируешь их, пытаешься повторить попытку или просто молча идёшь дальше?

Люди настаивают на конкретных исключениях вот почему: голый `except:` или `except Exception:` поймает буквально всё, включая то, чего ты не ожидал и, вероятно, не должен был игнорировать. Например, если ты пытаешься открыть файл и ловишь `FileNotFoundError`, это конкретно и имеет смысл. Но голый except поймает и такое, как `KeyboardInterrupt` или `SystemExit`, которые обычно нужно пропускать. Ещё хуже - это скрывает баги: если в твоём коде опечатка или логическая ошибка, которая вызывает что-то неожиданное, ты никогда это не увидишь, потому что блок except это проглотит.

С другой стороны, для небольших скриптов или быстрого кода народ прагматичен. Разница особенно видна при отладке или когда кто-то другой берёт твой код. Конкретные исключения ясно показывают твои намерения - этот код знает, как обработать отсутствующий файл, но не проблему с подключением к БД. Если ты пишешь что-то, что останется небольшим, ловля `Exception` (не голый `except`) намного безопаснее, чем всеобщий обработчик, и ты хотя бы сможешь видеть, что ловится. По мере роста проектов захочешь быть конкретнее. Привычка целенаправленно выбирать, что ловить - это не просто педантизм, это спасает от странных багов потом.

wind17 автор вопроса Пока что просто логирую их и иду дальше. В основном работаю с файлами и API в небольших скриптах, поэтому пока проблем не было, но я понимаю, что ты имеешь в виду насчёт скрытых багов.

Конкретные исключения лучше, чем универсальные, потому что ты поймаешь ошибки, которые не хотел пропустить - например, опечатку в имени переменной, которая вызывает `NameError`, а голый `except:` это скроет вместо того, чтобы дать тебе её исправить. Даже для небольших проектов эта привычка быстро себя окупает; можно всегда объединить связанные исключения вроде `except (ValueError, TypeError):`, если хочешь сохранить компактность.

Реальная ловушка, которую люди упускают: голый `except:` ловит даже `KeyboardInterrupt` и `SystemExit`, поэтому твоя программа может проигнорировать Ctrl+C пользователя и продолжить работу. Используй `except Exception:` как минимум, если тебе нужен универсальный обработчик, но честно, потрать 30 секунд на то, чтобы разобраться, что именно может пойти не так, и перечисли это.

Ваш ответ

Войдите, чтобы ответить.