Pull to refresh

Хабраподсветка или эксперименты в изолированном окружении Python

Reading time4 min
Views5K
Протестировать свежую версию любимого фреймоврка. Запустить приложение со специфичным набором библиотек. Установить необходимые библиотеки по списку зависимостей. Как решить все эти задачи не затронув системные файлы? В этой статье речь пойдет об утилитах virutalenv и pip.

Утилита vitrualenv предназначена для создания изолированных окружений Python. Под окружением понимается собственно интерпретатор и набор библиотек к нему. Утилита pip органично дополняет easy_install, делая установку пакетов еще проще. Подробную информацию о всех полезностях, которые virutalenv и pip дают разработчику, вы сможете узнать, посетив странички pypi.python.org/pypi/virtualenv и pypi.python.org/pypi/pip. Я же покажу на примере как все это можно использовать для экспериментов с проектами на языке Python.

Суть данного проекта предельно проста. Эта небольшая консольная программулька с именем hl.py будет раскрашивать исходный код скриптов для вставки в хабратопик. Через командую строку она принимает путь к файлу с исходником и язык, а в ответ печатает нужный html код. Например, вот так она раскрашивает сама себя:
$ ./ht.py ./hl.py python
Traceback (most recent call last):
  File "./hl.py", line 3, in <module>
    pkg_resources.require('lxml==2.2.2')
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 626, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 524, in resolve
    raise DistributionNotFound(req)  # XXX put more info here
pkg_resources.DistributionNotFound: lxml==2.2.2

Упс, не работает. Сообщение говорит о том, что не установлен дистрибутив lxml версии 2.2.2. Посмотрим, что есть в Ubuntu:
$ apt-cache show python-lxml | grep -E ^Version
Version: 2.1.5-1ubuntu2

Действительно есть что-то похожее, но, определенно, не той версии которая требует эта программулька. А как узнать, что такое lxml? Воспользуемся утилитой yolk (http://pypi.python.org/pypi/yolk).
$ yolk -f summary -M lxml
bash: yolk: команда не найдена
$ apt-cache search yolk
$

Почему разработчики Ubuntu не сделали пакет для такой полезной утилитки?…

Однако, это не проблема. У нас есть возможность сделать собственное окружение Python, не зависящее от причуд создателей дистрибутива операционной системы. Сохраните на диск следующий скрипт под именем vipsetup и сделайте его исполняемым:
#!/bin/sh
# Setup virtual environment for python and pip
# Usage:
#    vipsetup [directory]

ENV_DIR="$1"
VIRTUALENV_BIN='virtualenv'
VIRTUALENV_ARGS='--no-site-packages'

if [ ! -f $ENV_DIR/bin/activate ]; then
    if ! type "$VIRTUALENV_BIN"; then
        if ! type "easy_install"; then
            echo "Error: easy_install executable not found."
            echo "To install easy_install type:"
            echo "  sudo apt-get install python-setuptools"
            exit 1
        fi
        TMPDIR=`mktemp -d -t ve.XXXXXXXXXX` || exit 1
        PYTHONPATH=$TMPDIR easy_install --install-dir=$TMPDIR virtualenv || exit 1
        PYTHONPATH=$TMPDIR $TMPDIR/virtualenv "$@" $VIRTUALENV_ARGS || exit 1
        rm -rf $TMPDIR
    else
        $VIRTUALENV_BIN "$@" $VIRTUALENV_ARGS || exit 1
    fi
fi

if [ ! -e $ENV_DIR/bin/pip ]; then
    $ENV_DIR/bin/easy_install pip || exit 1
fi

echo ""
echo "Installation complete" 
echo "* To activate virtual environment type:"
echo "  . $ENV_DIR/bin/activate"
echo "* To install python package type:"
echo "  $ENV_DIR/bin/pip install <package>"

if [ -z "$PIP_DOWNLOAD_CACHE" ]; then
    echo "* To enable cache for downloads"
    echo "  set environment variable PIP_DOWNLOAD_CACHE with a path"
fi

Создайте новое изолированное окружение, при помощи команд:
$ mkdir -p /tmp/testenv
$ cd /tmp/testenv
$ vipsetup .
$ . /bin/activate
(testenv) $

А теперь установите yolk, используя команду pip:
(testenv) $ pip install yolk
...
(testenv) $ yolk -f summary -M lxml
summary: Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API.

Вот и описание. Установите lxml требуемой версии:
(testenv) $ pip install lxml==2.2.2

Теперь, все готово для запуска нашей программульки:
(testenv) $ ./hl.py ./hl.py python
#!/usr/bin/env python<br>import pkg_resources<br>
pkg_resources.require('lxml==2.2.2')<br>
 <br>from lxml.html import parse, submit_form, tostring<br>
 <br>def highlight(code, language):<br>
    SERVICE = 'http://highlight.hohli.com/'<br>
    doc = parse(SERVICE)<br>
    form = doc.getroot().forms[0 ]<br>
    form.fields['language'] = language<br>
    form.fields['use_font'] = 1 # for habrahabr<br>
    form.fields['code'] = code<br>
    form.action = form.action or form.base_url # hack<br>
    ans = parse(submit_form(form))<br>
    highlited = ans.getroot().cssselect('.source .src')[0 ]<br>
    return ''.join([tostring(x) for x in highlited]<br>
            ).replace('0</font>''0 </font>' # fix habrahabr <br>
            ).replace('blockquote>''code>') # fix format <br>
 <br>if __name__ == "__main__":<br>
    import sys<br>
    def main(*args, **kwargs):<br>
        fh = sys.stdin if args[0 ] == '-' else file(args[0 ])<br>
        language = args[1]<br>
        code = unicode(fh.read())<br>
        print highlight(code, language)<br>
        return 0 <br>
    sys.exit(main(*sys.argv[1:]))<br>
 

Вот она, вся такая цветная. Наслаждайтесь. :) И запишите где-нибудь список зависимостей, на память:
(testenv) $ pip freeze | tee requirements.txt<br>
lxml==2.2.2
wsgiref==0.1.2
yolk==0.4.1

Если потребуется, быстренько восстановите при помощи команды:
(testenv) $ pip install -r requirements.txt


зы: если практическая полезность данного эксперимента вам показалось сомнительной, сделайте:
(testenv) $ deactivate
$ rm -rf /tmp/testenv
и будем считать, что ничего не было. ;)
Tags:
Hubs:
+26
Comments11

Articles

Change theme settings