Скрипты и автоматизация
Что это такое
Python как язык автоматизации опирается на модули стандартной библиотеки: файлы и пути, дочерние процессы, даты, архивы, форматы структурированных данных, аргументы командной строки. Они заменяют сценарий оболочки, когда у того появляются ветвления, нужно разобрать документ или он должен работать на машине, где оболочка ведёт себя иначе, а в итоге получается программа, которую можно тестировать, переносить между платформами и читать любому, кто знает язык.
Почему это важно
Оболочка превосходна для конвейера из трёх команд и мучительна для всего, где есть условия. Как только скрипт разбирает JSON, повторяет сетевой вызов или должен вести себя одинаково на двух операционных системах, правила оболочки про кавычки и обработку ошибок становятся главным источником дефектов. Однако стандартная библиотека Python закрывает эти случаи без зависимостей, а важнее всего это там, где работает автоматизация: на сборочной машине, в контейнере, на сервере, куда трудно добавить пакеты.
Ключевые идеи
Работа с путями — дело библиотеки, а не склейки строк
Модули путей обрабатывают разделители, соединение, смену расширения и проверку существования так, как правильно на любой платформе. Сборка путей склейкой разделителей работает, пока код не запустят на машине другого вида, — и тогда он падает так, что это выглядит как пропавший файл, а не как ошибка.
from pathlib import Path
config = Path.cwd() / "config" / "app.yaml"
Дочерние процессы запускают с явными аргументами и с проверкой кода возврата
Запуск внешней команды со списком аргументов полностью снимает вопрос кавычек и убирает класс проблем с внедрением. Код возврата нужно проверять: дочерний процесс, который падает без исключения, позволяет скрипту продолжиться так, будто всё сработало, — обычный способ, которым задача автоматизации сообщает об успехе, ничего не сделав.
В автоматизации скрипт общается через код возврата, стандартный вывод и стандартный поток ошибок. Запись хода работы в поток ошибок оставляет поток вывода чистым для данных, а ненулевой код возврата при сбое позволяет вызывающему заметить проблему. Если скрипт всегда завершается нулём, в конвейере он бесполезен.
Датам и времени нужен явный часовой пояс
Наивные даты не несут пояса и молча сравниваются с чем угодно. Если привязать пояс там, где значение входит в программу, и преобразовывать его только для показа, ошибок на несколько часов не будет — тех самых, что всплывают дважды в год и после каждого развёртывания в другом регионе.
У форматов структурированных данных есть библиотеки, но проверка схемы всё равно нужна
Чтение и запись структурированных документов — вызов в одну строку, а проверка того, что в документе есть ожидаемые поля, — нет. Файлы конфигурации и ответы API меняются, и скрипт, который считает, что ключ существует, падает в самый неудобный момент. Проверка формы на границе превращает это в понятную ошибку.
Аргументы командной строки заслуживают объявленного интерфейса
Небольшой разбор аргументов даёт скрипту именованные опции, значения по умолчанию, типы и сгенерированную справку. Альтернатива — порядок позиционных аргументов, и именно из-за него скрипт нельзя запустить из записи cron через полгода после написания.
Именно идемпотентность делает автоматизацию безопасной для повторного запуска
Скрипт, который можно запустить дважды без вреда — создавая недостающее, а не падая на существующем, — можно повторить после частичного сбоя. Автоматизация, которую нужно запускать ровно один раз, требует надзора, а это уже противоречит её смыслу.
Практика
Замените конвейер оболочки
Возьмите сценарий оболочки, который перечисляет файлы, фильтрует их и запускает команду на каждом, и перепишите его на Python с библиотекой путей и проверяемым вызовом дочернего процесса.
Готово, когда: скрипт ведёт себя одинаково при обоих разделителях пути и завершается ненулём, когда дочерний процесс падает.
Сделайте скрипт безопасным для повторного запуска
Возьмите скрипт автоматизации, который падает, если его выходной каталог уже существует, и измените его так, чтобы он создавал недостающее и продолжал работу.
Готово, когда: два запуска подряд дают одно и то же конечное состояние и нулевой код возврата оба раза.
Частые ошибки
- Сборка путей склейкой строк — скрипт ломается на другой платформе; исправить: используйте библиотеку путей.
- Игнорирование кода возврата дочернего процесса — провалившаяся команда отчитывается как успех; исправить: проверяйте код возврата и реагируйте на него.
- Данные и ход работы вместе в стандартном выводе — потребитель не может их разделить; исправить: отправляйте ход работы в поток ошибок.
- Сравнение наивных дат — сравнения неверны между поясами и при переходе на летнее время; исправить: привязывайте пояс там, где значения входят в программу.
- Уверенность, что ключ конфигурации есть — сбой случается посреди выполнения; исправить: проверяйте форму документа на границе.
Что читать дальше
- Модули и упаковка (05-backend-data/03-python-programming/03-modules-and-packaging) — как организованы эти скрипты и записаны их зависимости.
- Программирование на Python (05-backend-data/03-python-programming) — язык, на котором написана эта автоматизация.
- Командная оболочка Unix (01-cs-fundamentals/13-unix-shell) — инструмент, который заменяет эта запись, когда сценарий перерастает несколько команд.