Makefile — умные шелл-скрипты для Джанго

    Make — одна из базовых утилит Юникса, есть на каждой юниксовой машине, и, к сожалению, неизвестная многим веб-разработчикам. В этой стате я покажу, как она может упростить работу, а сначала — постановка проблемы.


    Чтобы проект на Джанге или Рельсах развернуть на новом сервере, нужно выполнить команд пять-десять. Если разработчик поправил схему БД, ему надо выполнить пару команд и перезапустить сервер. Если изменили список сторонних пакетов, нужно пересобрать и перезапустить, ещё 2 команды. Поменял перевод — ещё две. А если поменял сразу 2 вещи, БД и перевод? Или 3? Нужно помнить, проверять, возможны ошибки. Но ведь мы пользуемся компьютером! Он достаточно умён, чтобы понять, чтó обновить. Представьте себе фабрику дрелей, где не сумели сделать шуруповёрт и работают отвёртками. Глупо, правда?

    То ли Джэфф Атвуд, то ли Пол Грэм как-то написал, что программисты должны тратить больше времени на разработку инструментов для самих себя. Раз мы пишем абстракции кода (функции, модули), чтобы уменьшить его повторения, то и инструментами тоже нужно заниматься, чтобы было меньше повторяющейся работы.

    Давайте посмотрим так: что нам вообще нужно в описанных выше случаях? (Установка, обновления.) Мы устанавливаем сервер чтобы он что сделал? Заработал. Мы обновляем пакеты и хотим что? Чтобы что-то поменялось, и сервер снова заработал. Нам не важно как, главное — побыстрее, то есть чтобы лишнее не обновлялось.

    Конечно, на все эти случаи можно написать скрипты, только опять же придётся помнить, какой для чего. Запустишь не тот — и время теряется.

    На схеме в начале статьи — действия, которые нужно выполнять в моём проекте fastdev-django. До недавнего времени мне приходилось, по сути, приходилось держать аналог этой схемы в голове и каждый раз вспоминать, что делать. Однако конечные цели в схеме — только те, что выделены жёлтым цветом. Остальные действия — промежуточные остановки, и хорошая система должна сделать так, чтобы я про них не вспоминал.

    Решение



    Утилита Make вполне гибкая и может отследить точно, что нужно пересобрать, чтобы всё было обновлено, и при этом не пересобирать лишнее. Вот как выглядит правило в Makefile о том, что серверу Джанго нужно:

    .PHONY: run
    run: bin/django syncdb bin/sass compile_trans
    	./bin/django runserver 0.0.0.0:8000
    
    .PHONY: shell_plus
    shell_plus: bin/django syncdb bin/sass
    	./bin/django shell_plus
    
    bin/django: bin/buildout buildout.cfg
    	./bin/buildout
    
    bin/buildout:
    	python bootstrap.py --distribute
    
    syncdb: bin/django
    	./bin/django syncdb
    	# touch a timestamp file to avoid re-syncing
    	touch syncdb  
    
    make_trans: bin/django
    	./bin/django makemessages -a -e 'py,html,haml'
    
    bin/sass:
    	gem install sass --bindir bin
    
    # watch buildout.cfg
    buildout.cfg:
    
    compile_trans:
    	make locale/*/LC_MESSAGES/django.mo
    
    locale/%/LC_MESSAGES/django.mo: locale/%/LC_MESSAGES/django.po
    	./bin/django compilemessages -l $(word 2,$(subst /, ,$@))
    
    locale/*/LC_MESSAGES/django.po:

    (полный текст файла)

    Когда есть такой файл, работа становится проще:

    1. Поменял перевод — и если надо посмотреть его, идёшь в консоль и пишешь make run. А если не нужно сразу смотреть, просто правишь перевод. В другой раз обновится.
    2. Добавил пакеты в зависимости — просто перезапускаешь сервер через make run или консоль в make shell_plus.

    Здесь я не буду описывать, как пишутся Makefile, для этого достаточно материалов в Сети: книга от O'Reilly (на английском), руководство на русском, книга Эффективное использование GNU Make.

    Удалось настроить файл так, чтобы компилировались любые переводы (не конкретные файлы), но только обновлённые.

    Не удалось автоматизировать миграцию базы данных. Конечно, можно написать команду, которая будет удалять БД и пересоздавать её, но это опасно для рабочего сервера. Есть более тонкий инструмент, South, но пока что (версия 0.7.3) лучше не вызывать его автоматически. Если мы будем записывать каждое изменение БД в миграцию (в них записывается и дэльты, и полное состояние таблиц), то произойдёт вот что: я добавил поле, появилась миграция. Потом я поработал, ещё не коммитил ничего, но удалил это поле. Ещё одна миграция появилась на диске. Я сохранил файлы в СУВ, отправил другим разработчикам. Они должны будут запустить ненужные миграции, а репозиторий разбухáет от ненужных файлов.

    Листинг: файлы в папке миграций. 0002 создаёт поле, 0003 удаляет его. Размер каждого — 17 килобайт!
    29K 2011-10-13 12:33 0001_initial.py
    17K 2011-11-13 02:07 0002_auto__add_field_address_test_field.py
    17K 2011-11-13 02:07 0003_auto__del_field_address_test_field.py


    Если же отключить автоматический запуск South, придётся помнить, какие изменения происходят в БД. И тут мы возвращаемся к началу статьи: мы должны помнить то, что может помнить компьютер.

    Культура работы



    Как-то раз я услышал такой аргумент: «Пусть разработчик помнит. Помнить и перепроверять всё — это вопрос культуры работы.» Пока я сам программировал на C и PHP, я тоже думал, что надо быть внимательным и, к примеру, прилежно ходить в Вики проекта, чтобы поддерживать там документацию своей библиотеки. В Питоне же есть docstring, и описание модуля, класса или метода лежат рядом с кодом. Тот же результат достигается меньшими усилиями, и ошибки случаются реже: глядя в код можно проверить, не устарела ли документация.



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


    Шасси Ан-124, Airliners.net

    Поэтому я считаю, что культура работы — наоборот, уменьшать нагрузку на память и упрощать работу, экономить время людей (если экономия стоит того, конечно), а так же образовывать работников, чтобы они при необходимости могли починить свои инструменты.

    Что дальше



    1. Перезапускать сервер, когда обновляешь перевод — тоже трата времени, особенно если есть автоперезапуск. Хочу пропатчить django.utils.autoreload, чтобы он следил не только за загруженными модулями, но и за текстовыми и компилированными переводами.

    2. В синтаксисе Make есть и переменные, и функции, и ленивые вычисления. Это ещё один язык разметки, который надо помнить. Неплохо было бы писать такое же, но на Питоне? Стоит попробовать SCons. Однако он есть не на всех системах, а Make есть и Линуксах, и на Маках.

    Литература



    1. GNU Make, O'Reilly, 2003
    2. Руководство по GNU Make
    3. Эффективное использование GNU Make, Владимир Игнатов, 2000
    4. Python's Makefile, Ian Bicking
    5. Документация по setuptools


    Добавление: в комментариях artifex подсказывает систему Fabric, скрипты похожие на Make на Питоне. По-моему, самая удобная из предложенных.

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 27

      0
      Кстати, make-утилиты есть и для windows, что очень сильно облегчает жизнь при разработке под windows.
      gnuwin32.sourceforge.net/packages.html
        0
        Есть вроде CMake, которая кросс-платформенная :)
          0
          … которая делает совсем не то, что делает make — а лишь генерируешь Makefile'ы и проекты соответствущих форматов под ту платформу, под которую попросишь…
            0
            Тогда есть waf.
          0
          всё равно пд виндой проктически невозможно разработывать под джангу… постоянно какие-то грабли
          +1
          Посмотрите в сторону python-doit.
            0
            Да, пакет интересный, в хозяйстве может пригодиться. Жалко что он не стоит везде сразу по умолчанию. :)
            0
            Вы отстали от жизни на очень много лет. Это сейчас делается с помощью capistrano и гораздо удобнее, потому что синтаксис make страшен и ненужен.
              +1
              Тоже хорошая вещь. Зато на Make я могу разворачивать проект на хостинге, не устанавливая никакого дополнительного софта.
                0
                Всё-таки, по сравнению с fabric, простые команды в make пишутся проще.
                  0
                  local(«command») VS `command`
                  А что выберешь ты, %user_name%?
                +13
                Разве не удобнее писать fab-скрипты для таких задач?
                  0
                  Монжо ссылку на документацию?
                    +4
                    Сам Fabric: docs.fabfile.org/en/1.2.0/index.html
                    Полуфабрикат для Django: packages.python.org/django-fab-deploy/
                      0
                      Вспомнил, что видел его в исходниках одного проекта. Если сильнее внедряться в Джангу, то очень удобно. django-fab не совсем подходит, потому что не пользуюсь ни virtualenv (а zc.buildout), ни MySQL.
                    0
                    А я им говорил, но нет. Для них Make понимаешь ли святое.
                      –2
                      Ну что же, Вы, минусуете? Обьясните свою точку зрения, никто же не мешает.
                      Под виндой у вас есть мэйк? А вот питон ставиться. (Дада есть всякие порты мэйка, сигвин, МСИС...) и ставить его только ради деплоя — веселуха начинается сегодня! :D

                      У меня и так осталось чучуть кармы что бы я мог оформлять нормально комментарии. :(
                        0
                        Остальные парни тут написали конкретные полезные вещи. А вам моя точка зрения зачем? Она снимет ваше раздражение, придаст чувства собственной значимости? :)
                          –2
                          «придаст чувства собственной значимости» — это вы мощно пошутили. Никому мы нафиг ничего не значим, а в масштабах вселенной нас, можно считать, не существует.

                          Ваша (обощенно) точка зрения мне интересна. Возможно позволит взглянуть на свою и поменять, пригодится в будущем, ну и интересно как другие хомосапиенсы думают :)
                  • UFO just landed and posted this here
                      +3
                      make замечательный инструмент, но я отдаю предпочтение нативному для Python SCons (http://www.scons.org/). Кстати Google Chrome им тоже собирают.
                        –4
                        прошел по диагонали, суть вода. как можно забыть такие короткие команды, не понимаю. документирование в коде есть и для пыха и для сей, культура разработки автора такова, очевидно, что он аж своего кода не заскринил. что сказать-то хотел? умный человек сам себе мейкфайл набросает при необходимости, новичку же нужно понимать как что работает…
                          0
                          Соврамши, Миша, плохо читали. Новички прочтут и пусть дальше читают примеры из литературы. А команды совсем не короткие, набирать их каждый раз не охота.
                          0
                          Писал статью по этому поводу: pusto.org/naspeh/python-code-management/

                          сравнивается 3 подхода: make, fabric, pure python

                          еще есть python-doit.sourceforge.net/ paver.github.com/paver/ из той же темы.
                            +1
                            У вас странные проблемы с South. Мы работаем с этой штукой уже довольно долго, очень довольны. При изменении моделей запускаю schemamigration и migrate, дальше South сам все делает. Если решил, что базу не надо править — удалил файлы миграций перед коммитом, и все осталось как было.
                              0
                              Проглядел такой вариант. Спасибо!
                              0
                              Проглядел такой вариант. Спасибо!

                              Only users with full accounts can post comments. Log in, please.