Архив за [undefined]

Открываю для себя WSGI

Причина

Проблема развертывания джанго приложений в продакшене до недавнего времени у меня стояла остро. Моя стандартная связка nginx+threaded fastcgi(flup) была очень не стабильна. Из-за достаточно ограниченных ресурсов (памяти) на серверах (в основном впс с лимитом до 100мб). Постоянно приходилось перезагружать сервер из-за сжирания памяти (неужели в питоне есть утечки памяти, или это из-за корявости моих скриптов?) и умирании процесса. Хорошо когда это было запланировано, а когда случалось неожиданно - это была маленькая катастрофа. Заказчики ругались.

Но в этой связке меня подкупала легковесность nginx и простота настройки. Изначально я ещё попробовал mod_python и apache, но не впечатлило - медленно и сложно. Фастсиджиай работал быстро и радовал глаз (пока работал).

Моя находка

Как то однажды, достаточно давно, заметил в одной из рсс упоминание о WSGI интерфейсе. Быстро осмотрел, понял что к чему и благополучно забыл (был занят другими более важными делами). Но тут уж пришел край и занялся я плотно поиском альтернативы системы размещения, которую я использовал. Тут как нельзя лучше подвернулся пост Пираньи в котором он упоминается mod_wsgi для nginx, нагрянули воспоминания, была поднята "подшивка" рсс (желтые звездочки в ридере рулят:) ) и начался процесс глубокого изучения этой штуки под названием wsgi.

Замечания того же Пираньи, что модуль для nginx'а ещё ...

Не SQL'ем единым или как я попробовал buzhug

Недавно встала задача реализовать один сервис(аналог cron) на питоне. Для души так сказать. Одна из подзадачь: организация хранения данных. При первой итерации было решено использовать SQLite бэкэнд. Поскольку одним из требований к сервису был малый объем занимаемой памяти в процессе работы, т.к. ресурсы моего впс ограничены. Но после маленьких испытаний я понял, то SQLite не очень интересен для меня, как для вечно что-то новое пробующего разработчика, и не так уж и лайт, да и ничего нового. Подумал, а почему бы не использовать какой-нибудь из ORM движков. Стал пробовать и SQLAlchemy и SQLObject. Но эти варианты отпугнули своей тяжеловесность, хотя и интересны в плане изучения не джанговского ORM.

И вот однажды, на одном из регулярно читаемых мной форумов заприметил упоминание одной очень занятной библиотеки buzhug. Как обещают её авторы - мне не надо будет писать SQL запросы, а придется писать list comprehensions or generator expressions. Заманчиво и интересно.

Попробовал пример из туториала. Понравилось ещё больше. Всё просто и прозрачно. Решил остановить свой выбор на этой библиотеке и познакомиться с ней поближе.

Когда сервис был завершен в своей первой редакции, я осознал, что сделал правильный выбор. Код получился лаконичным и действительно без SQL запросов. Работать с данными удобно. Немного напрягло то ...

switch/case в шаблонах

Недавно заприметил один, как мне показалось, занимательный снипет. Это простая реализация конструкции switch/case конструкции для джанго шаблонов. Хотя позиция разработчиков джанги, что шаблонный язык(хотя они говорят даже, что это не язык вовсе) должен быть максимально прост и не напрягать дизайнера/верстальщика своими наворотами. Но такая конструкция из привычный языков программирования высокого уровня вполне была бы к месту.

В базовой поставке кроме вариаций на тему if - тегов условий нет. Вот этот снипет и пытает расширить семантику шаблонизатора в "условном" направлении. Но в нем отсутствуют такие вещи как: default значение и множественный(не правильное наверно слово подобрал) кейс.

Я решил немного доработать и избавить реализацию от ограничений.

Вот мой вариант(файл можно взять отсюда):

from django import template

register = template.Library()

@register.tag
def switch(parser, token):
    """
    Switch tag.  Usage::

        {% switch meal %}
            {% case "spam" %}...{% endcase %}
            {% case "eggs" %}...{% endcase %}
        {% endswitch %}

    Note that ``{% case %}`` arguments can be variables if you like (as can
    switch arguments, buts that's a bit silly).
    """
    # Parse out the arguments.
    args = token.split_contents()
    if len(args) != 2:
        raise template.TemplateSyntaxError("%s tag tags exactly 2 arguments." % args[0])

    # Pull out all the children of the switch tag (until {% endswitch %}).
    childnodes = parser.parse(("endswitch",))

    # Remove the {% endswitch %} node ...

Что под капотом?

И так, поскольку этот блог является примером проекта написанного на django, то я пожалуй расскажу про его техническую реализацию.

Описание:

  • VPS от FirstVDS.ru
    • Сервер 192МБ RAM(мне кажется, что это очень важная деталь)
    • На том же аккаунте крутится ещё один сайт.
  • Python 2.5
  • Nginx в роли прокси к threaded flup fastcgi серверу
  • Django trunk
  • Планируется индексирование контента с помощью xapian. В процессе разработки. Есть плохая реализация. Сейчас провожу рефакторинг
  • дополнительные библиотеки:
    • PIL - для обработки изображений
    • pytils - для создания slug'ов с транслитерацией
    • pyCaptcha - для капчи в форме добавления комментария и обратной связи.
  • Инстанс сайта в среднем "отжирает" 25мб. Что как мне кажется достаточно много.

    Особенности:

  • Проект блога состоит только из внешних универсальных модулей: блоги, профайл, обратная связь и т.д. Которые не знают о существовании друг друга. Это очень характеризует возможности django в плане способствования четкому модульному разделению.

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

Обновление от января 2008

  • Теперь блог хостится в Tektonic
  • Памяти стало 256мб Но на том же ...

Быстро меняющийся транк

Наверно многие как и я активно следят за изменениями в транке джанго. Но не всегда есть возможность мониторить user groups, а вот самого от trac'а получить нужную информацию можно легко.

Он предоставляет rss фид по всем изменениям в вики. Его я и решил забросить себе в reader. Но поскольку страница BackwardsIncompatibleChanges ( где отмечаются радикальные изменения в джанго ) наверно сама интересная в моём случае, то надо как-то отфильтровать именно изменения в ней.

На помощь пришел сервис yahoo! pipes. Замечательное приложения в сегодняшнем мире повальной агрегации контента из разных источников. В нем легко можно составить пайп с необходимыми фильтрами.

На досуге я решил попробовать этот сервис в действии( я долго ждал реальной задачи, чтобы испытать его ) и вот что у меня получилось:

Django BackwardsIncompatibleChanges updates

yahoo! pipes мне очень понравился, поэтому скоро может напишу развернутый пост про него. Всем советую попробовать.