Python, Django: внешние скрипты

При работе с Django иногда возникает необходимость запустить скрипт, написанный на Python, который бы мог использовать функционал Django, не используя веб-интерфейс, например вызвать такой скрипт из Cron.

Введение

Что имеется в виду в названии? Имеется в виду вот что. Django это фреймворк для построения веб приложений. т.е. все обращения к его составным частям происходят через веб сервер, при запросе браузером веб страницы. Это штатный режим работы.

Но иногда у нас может возникнуть непреодолимое желание использовать составные части Django из скрипта, написанного на Python и запускаемого как обычное приложение. Для чего это может понадобиться? Да мало ли. Ну например захотим мы по крону раз в сутки собирать статистику из базы данных, которую использует наше веб приложение и отправлять ее по почте. Или еще, редактируем статьи в своем блоге и хотим отправлять их не через веб-интерфейс, а прямо из редактора, сохранив файл и запустив на выполнение скрипт. Это позволит нам серьезно ускорить работу, за счет сокращения нажатия клавиш и тыканья мышкой.

В общем-то ничего сложного в использовании Django в скриптах нет. Но, нужно правильно подготовить окружение. Вот этим и займемся.

Постановка задачи

Итак, давайте попробуем сделать свои скрипты. Делать их будем на примере подготовки статей для блога. Исходные данные:

  • Статьи лежат каждая в своей директории. Имя файла с текстом статьи: "body.html"
  • В том же директории лежит файл info.py, с конфигурационной информацией, нужной для работы скриптов (id записи, в которой храниться текст статьи).
  • Проект блога испольует свое окружение, в котором установлена своя копия Python, библиотек и Django.
  • Для редактирования статей испольуем Emacs. К делу это относиться мало, можно и Vi и другой редактор, но все-таки.

План решения задачи

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

  • Запускаем скрипт на Shell. Он подготовит окружение для запуска другого скрипта, уже на Python.
  • Скрипт на Python проимпортирует нужные библиотеки Django.
  • Скрипт на Python выполнит нужную работу.
  • Конец плана

План готов, поехали.

Подготовка окружения в shell

Так как я использую для установки Django, виртуальные окружения, т.е. свою отдельную установку Python, его библиотек, самого Django, то просто запустить основной Python не получится. Нужно поменять директорий на директорию, в которой установлен проект. После этого нужно активизировать виртуальное окружение. Все это делает скрипт, приведенный ниже. Более подробно:

  • Строка 3: Запомнили в переменной окружения директорию, в которой лежит статья.
  • Строка 6: Переходим в директорий, в котором установлен проект Django.
  • Строка 7: Выполняем установку виртуальное окружение.
  • Строка 9: Запускаем скрипт на Python.
 1 #! /bin/bash
 2 
 3 export ARTICLE_DIR=`pwd`
 4 PYTHON_SCRIPT=${HOME}"/bin/__insert_article_blog.py"
 5 
 6 cd ../../www
 7 source env/bin/activate
 8 
 9 python  $PYTHON_SCRIPT
10 
11 exit 0

  

Работа скрипта на Python

Ну вот и собственно скрипт, который выполняет основную работу. Последовательность, описываю только важные части:

  • Строка 3: Добавляем путь к директории, в которой установлен проект Django к системному пути Python. Без этого не сможем импортировать установленные приложения.
  • Строка 16: Импортируем наши настройки.
  • Строки 18 - 24: Ну ясно, читаем файл.
  • Строки 26 - 28: Собственно использование ORM Django. Запихиваем нашу статью в базу данных. info.article_id это наши настройки из файла info.py.
 1 # -*- coding: utf-8 -*-
 2 import os,sys,codecs
 3 sys.path.append(os.path.join(os.path.abspath('..'), 'www'))
 4 from django.core.management import setup_environ
 5 from blog import settings
 6 setup_environ(settings)
 7 
 8 from blog.myblog_seo.models import MyBlogSeo
 9 from diario.models import Entry
10 
11 article_dir = os.getenv('ARTICLE_DIR')
12 article_body_file = 'body.html'
13 sys.path.append(article_dir)
14 a_body_file = os.path.join(article_dir,article_body_file)
15 
16 import info
17 
18 try:
19     fd = codecs.open(a_body_file,encoding='utf-8',mode='r')
20     article_text = fd.read( )
21 except:
22     print >> sys.stderr, "Can not read file: ",a_body_file
23     sys.exit(1)
24 fd.close( )
25 
26 r = MyBlogSeo.objects.get(id=info.article_id)
27 r.body_source = article_text
28 r.save()
29     

  

Для справки, файл info.py:

1 # -*- coding: utf-8 -*-
2 
3 article_id = 10

  

Значение id подсматриваем в базе.

Заключение

Итак, раньше я работал так, редактировал текст статьи в emacs, потом копировал тело статьи в админку, сохранял тело статьи и после этого мог смотреть статью в браузере. Теперь работа выглядит так:

  • Заводим в админке новую статью.
  • Смотрим, какой у нее id и записываем его в файл info.py
  • Редактируем тело статьи в emacs.
  • Прямо из emacs жмем C-S ! и запускаем скрипт загрузки статьи в базу.
  • Все, можно смотреть статью.

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

На самом деле, в скрипте на Python у меня еще прикручена обработка самодельного тэга, для вызова внешней программы code2html. что дает мне подсветку кода скриптов. Но это уже совсем другая история...

Опубликовано: September 27, 2010

Комментарии:


Имя: pkolt

Как мне кажется более элегантным и простым решением будет добавить свою команду в manage.py, тем более что это итак будет вынесено в отдельный скрипт http://docs.djangoproject.com/en/1.2/howto/custom-management-commands/



Имя: evgeny

К сожалению, случайно удалил целую длинную цепь комментариев, посвященных как раз этому. Вкратце, мое мнение. Какие-то задачи удобнее размещать в как кастомные команды, какие-то как внешние скрипты. У меня традиционно такие скрипты лежат в $HOME/bin.



Имя: oduvan

Не знаю, как сейчас, но в последний раз мне пришлось отказаться от скрипта в пользу команды, из-за того, что не ходили сигналы



Имя: Evgeny

Во многих случаях, конечно лучше команды.



Имя: вап

вапв



Комментировать:

Имя:

Комментарий: