Многие пишут так:
try:
...
except (ValueError, TypeError, KeyError, NameError):
print("Что-то пошло не так")
Выглядит «надёжно». Но на практике такой код часто прячет реальные баги и усложняет отладку.
Допустим, вы читаете CSV с датами и хотите обработать ошибки:
try:
start = parse_date(row["start"])
end = parse_date(row["end"])
except (ValueError, TypeError, KeyError, NameError):
print("Некорректная дата")
На первый взгляд — всё ок. Но проблема в деталях.
1.
NameError здесь вообще лишнийNameError обычно означает баг в коде.Например, вы случайно написали:
star_date
вместо
start_date
Если ловить
NameError, программа просто проглотит ошибку — и вы даже не заметите, что сломали код.Иногда traceback — это полезно.
2.
ValueError — логичная ошибкаЕсли в CSV дата битая:
2026-00-01
то
datetime честно скажет:
ValueError
Это уже ошибка данных пользователя — её как раз нормально обрабатывать.
3.
TypeError — тоже может быть валидным кейсомНапример, если дата отсутствует:
name,start,end
Q1,2025-01-01,
Тут программа получает
None вместо даты. Это проблема входных данных, а не вашего кода — обработать её можно.4.
KeyError — не всегда стоит ловитьЕсли пользователь ошибся в заголовке:
name,Start,end
(большая
S вместо маленькой)код выдаст:
KeyError: 'start'
И это… полезная ошибка.
Если вы её поймаете и покажете:
> Invalid date on line 1
пользователь вообще не поймёт, что проблема в заголовке.
Лучше проверить headers заранее:
required = ["name", "start", "end"]
for col in required:
if col not in reader.fieldnames:
print(f"Missing column: {col}")
sys.exit(1)
Когда
except Exception всё-таки нормаленЕсть исключение из правила: mission-critical код. Например, вы обрабатываете 1000 файлов и не хотите, чтобы один битый файл остановил весь процесс.
Тогда такой код оправдан:
for path in files:
try:
process(path)
except Exception as e:
log_error(path, e)
Один файл упал → идём дальше. Главное — логировать ошибку, а не silently ignore.
📍 Навигация: Вакансии • Задачи • Собесы
Библиотека питониста
#буст