Логирование и обработка ошибок

Скрипт, работающий без присмотра, обязан рассказывать о себе. Модуль logging ведёт журнал событий, а try/except не даёт одной ошибке уронить весь пайплайн.
Суть: logging вместо print — с уровнями, временем и записью в файл. try/except ловит ошибку, чтобы скрипт продолжил работу и записал, что пошло не так.

Когда скрипт запускается ночью по cron, рядом никого нет. Если он молча упадёт, вы узнаете об этом утром по отсутствию отчёта — и не поймёте, что случилось. Поэтому надёжная автоматизация всегда логирует свои действия и обрабатывает ошибки. Модуль logging из stdlib ведёт журнал с временными метками и уровнями важности; всё это работает в браузере.

Уровни логов — это градация важности: DEBUG (детали для отладки), INFO (нормальный ход), WARNING (подозрительно), ERROR (сбой). Настроив порог, вы фильтруете шум. Разберём logging и обработку ошибок прямо в браузере.

Попробуй сам ▶

import logging

logging.basicConfig(level=logging.INFO,
    format='%(levelname)s: %(message)s')

def process(file, ok):
    # try/except: одна плохая запись не валит весь цикл
    try:
        if not ok:
            raise ValueError('битые данные')
        logging.info(f'{file}: обработан')
        return True
    except ValueError as e:
        logging.error(f'{file}: пропущен — {e}')
        return False

files = [('jan.csv', True), ('feb.csv', False), ('mar.csv', True)]
done = sum(process(f, ok) for f, ok in files)
logging.warning(f'Готово: {done} из {len(files)} файлов')
# feb.csv упал, но mar.csv всё равно обработался

Ключевая мысль: feb.csv сломался, но цикл не остановился — ошибка поймана, записана в лог, и обработка пошла дальше. Без try/except первый же сбой уронил бы весь скрипт, и валидные файлы остались бы необработанными.

УСТОЙЧИВЫЙ ПАЙПЛАЙН

  для каждого элемента:
    try:
      обработать  --ok-->  log INFO  -> дальше
    except:
      log ERROR   --------------------> дальше

  итог: log WARNING 'N из M успешно'
  один сбой НЕ останавливает остальные

В реальном скрипте логи пишут в файл, чтобы наутро посмотреть историю. Настройка записи в файл показана как врезка — она трогает диск.

import logging

logging.basicConfig(
    filename='automation.log',
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S')

try:
    run_pipeline()
    logging.info('Пайплайн завершён успешно')
except Exception as e:
    # exc_info=True добавит полный стек ошибки в лог
    logging.error('Пайплайн упал', exc_info=True)
    raise

Логирование раскрывает свою силу в связке с уведомлениями: критическую ошибку мало записать в файл — о ней нужно узнать сразу. Поэтому в продакшене к logging часто подключают обработчик, который при уровне ERROR не только пишет в журнал, но и шлёт сообщение в почту или мессенджер. Так ночное падение бэкапа не останется незамеченным до утра. Полезно различать и стратегии реакции на сбой: иногда правильно пропустить плохой элемент и продолжить (обработка пачки файлов), а иногда — немедленно остановиться и поднять тревогу (ошибка в финансовом расчёте). Осознанный выбор между «продолжить» и «упасть громко» — признак зрелой автоматизации.

Как работает под капотом

Когда возникает ошибка, Python создаёт объект исключения и начинает «всплывать» вверх по стеку вызовов, пока кто-нибудь его не поймает блоком except. Если никто не ловит — программа падает с трассировкой. try/except ставит «сетку»: код в try выполняется, а если в нём вылетело подходящее исключение, управление переходит в except, и скрипт продолжает жить.

Модуль logging устроен как конвейер: ваше сообщение проходит через фильтр уровня, форматтер (который добавляет время и уровень) и обработчик (который решает, куда писать — в консоль или файл). Параметр exc_info=True просит logging приложить полную трассировку ошибки — бесценно при ночных падениях.

Частые ошибки

  • Голый except:. Перехват всех исключений подряд прячет даже опечатки в коде. Ловите конкретные типы.
  • print вместо logging. print не даёт уровней, времени и записи в файл; для автоматизации он слеп.
  • Глотать ошибку молча. except: pass скрывает проблему — вы не узнаете, что половина данных потерялась.

Best practices

  • Логируйте начало, конец и каждый сбой; пишите логи в файл с временными метками.
  • Ловите конкретные исключения, а не всё подряд; используйте exc_info=True для трассировки.
  • Решите осознанно: пропустить плохой элемент и продолжить или остановить весь пайплайн.

Итоги. logging и try/except превращают хрупкий скрипт в надёжную службу: журнал событий, перехват ошибок, понятные сообщения. Теперь соберём все навыки курса в один полноценный проект автоматизации.

Проверьте себя
1. Что произойдёт в цикле обработки файлов, если обернуть тело в try/except?
AВесь цикл остановится на первой ошибке
BОшибка одного файла будет поймана, и цикл продолжит с остальными
CОшибки будут проигнорированы без следа
DЦикл выполнится дважды
2. Почему logging предпочтительнее print в автоматизации?
Alogging работает быстрее
Blogging даёт уровни важности, время и запись в файл для разбора потом
Cprint не умеет выводить кириллицу
Dlogging не требует импорта