вторник, 15 мая 2012 г.

virtualenv в помощь

В этой статье хочу поделиться опытом того, как можно без лишней головной боли организовать тестирование web-приложения , написанного на python c различными версиями этого языка. И даже с различными версиями того или иного фреймворка (django, pylons etc)...если, конечно , фреймворк используется.
Итак , есть сервер , для определенности : на нем установлен linux.. для еще большей определенности - debian )
Любой linux - дистрибутив уже включает в себя ту или иную версию python. Допустим "из коробки" имеем python v2.5. Мы же хотим протестировать наше гипотетическое приложение на совместимость с python 2.5, 2.6 и 2.7 (на совместимость с версией 3 лучше не тестировать - под нее надо писать отдельно =), чтобы быть уверенным, что наше приложение будет работать на большинстве python-хостингов.
  1. доставляем отсутствующие версии python. Для этого wget-ом, например, выкачиваем соответствующие исходники, распаковываем (tar), конфигурируем НЕ ЗАБЫВАЯ УКАЗЫВАТЬ ПРЕФИКС установки отдельно для каждой версии python, затем make и make install. В итоге получаем:
    • /usr/bin/python - дефолтный
    • /usr/python2.6/bin/python
    • /usr/python2.7/bin/python
  2. теперь самое интересное - у нас три одинаковых бинаря python в трех разных местах. Если вызвать python из командной строки, то будет дернут тот, чей путь левее всего в PATH. Как быть? каждый раз руками менять PATH? мучаться с симлинками? Слава Богу нет. Нам на помощь приходит замечательная штукенция - virtualenv !
    
    sudo apt-get install virtualenv
    mkdir ~/projects/
    cd projects
    virtualenv --no-site-packages -p /usr/bin/python app_test_python2.5
    virtualenv --no-site-packages -p /usr/python2.6/bin/python app_test_python2.6
    virtualenv --no-site-packages -p /usr/python2.7/bin/python app_test_python2.7
    
    В результате мы имеем три директории - по одной для каждой версии питона. Интересное внутри этих директорий. Внутри же создается окружение - бинари, инсталляторы библиотек (pip , easy_install) - сюда же надо помещать и код тестируемого приложения, отсюда же и деплоить с локальным web-сервером (apache, nginx..)
  3. еще не все. Чтобы работать в окружении , надо его активировать:
    
    cd ~projects/app_test_python2.6
    . env/bin/activate
    
    
    теперь можно не боясь вызвать python, pip, easy_install - будет вызвана именно версия 2.6, будут использованы именно библиотеки для версии 2.6 и ставиться будут они не в /usr/lib/python , а в ~projects/app_test_python2.6/lib !
Полная изоляция, никакой мороки и путаницы.
Таким образом, создавая для каждой тестовой конфигурации свое виртуальное окружение, мы не засираем систему хаотичными симлинками, конфликтующими версиями библиотек и т.д. и т.п. В общем сплошные плюсы.
Расписал, конечно, не все максимально детально. Но, думаю, тому , кто решить освоить эту технику организации тестовых стендов помогут гугл, здравый смысл и прямые руки )
p.s. только python к сожалению ( Пока писал стало интересно есть ли аналоги для perl, php ... )

14 комментариев:

  1. > Полная изоляция

    Ну... нет. Закон дырявых абстракций никто еще не отменял.

    ОтветитьУдалить
    Ответы
    1. А что он гласит и как его тут применить , не подскажете? )

      Удалить
    2. http://www.joelonsoftware.com/articles/LeakyAbstractions.html

      Я в свое время набил много шишек с виртуализацией вообще и с virtualenv в частности. Их не так много, но они очень неприятный и сложно диагностируемые. С тех пор стараюсь на рабочей машинке среду для тестирования не разворачивать.

      Это не значит что virtualenv это плохо. Просто желательно хорошенько разобраться с тем как оно работает и внимательно следить за вот такими штуками: https://github.com/pypa/virtualenv/issues?state=open

      А то у того же virtualenv пару лет назад были "веселые" баги с SSL, например...

      Удалить
    3. Наверное за последний год подчистили изрядно эту тулзу, так как я серьезных шишек не припомню. Зато очень хорошо помню "пляски с бубном" , когда надо было держать несколько питонов и django на одной машине. virtualenv в такой ситуации незаменим.
      Если пользоваться --no-site-packages (сейчас это уже дефолтное поведение утилиты и эту опцию можно даже не указывать), то изоляция будет максимальной. При том, что баги, конечно, не исключаются - это ведь тоже софт :)
      Можно , конечно же, для каждой версии питона создавать свою виртуальную машину , чтобы уж ну совсем заизолировать. Но это на порядок более громоздко.

      Удалить
    4. Как и любая тулза - она развивается. Старые баги закрывают, новые открывают. Можешь пошарить официальный багтрекер - неприятных хватает. Просто не факт что они для твоего конкретного случая хоть как-то актуальны. Ряд проблем не столько функциональные косяки, сколько всякие рейскондишены и плохое конкурентное использование ресурсов. Чтобы их словить, надо хорошенько поднапрячь приложения. В обычном размеренном функциональном тестирование вероятность маленькая, но есть.

      Опять же - стабильная шишка #1 это апгрейд питона (да и просто неаккуратные движания в глобальных питониевых либах). Если у тебя куча virtualenv'ов, то удачи восстанавливать линки.

      Совсем хорошая изоляция, когда у тебя на каждый сетап свой virtualenv который крутится в отдельном virtualbox'е. Рулить этим всем через какой-нибудь vagrant и т.п. Это позволит работать в среде +\- близкой к продакшену (если у вас таковой вообще есть). Еще лучше, если все это еще и по физическим машинам разнесено, т.к. даже такая виртуализация течет. Но это дорого.

      virtualenv хорошая штука, просто нет там тотальной изоляции и быть не может. Но при этом есть различные уровни достаточной для ряда задач. Потому и хорошая

      Удалить
  2. "полная изоляция" пометил в тексте особым стилем ;)

    ОтветитьУдалить
  3. Не пойму как пользоваться.
    В обычном питоне установлен selenium и Pyside. Создаю окружение с опцией --no-site-packages(т.е без пакетов).
    Активирую, вызываю необходимый скрипт и он нормально работает! Т.е по идее должен жаловаться на отсутствие селениума и пикьюта, но ничего этого нет и видимо запускается обычный питон.
    Что я делаю не так? Спасибо.

    ОтветитьУдалить
    Ответы
    1. Устанавливается в окружение все нормально, т.е не затрагивая обычный python

      Удалить
    2. Чтобы понять, какой питон используется , выполните команду which python ( после активации вирт.окружения, естественно )...

      На всякий случай привожу последовательность команд:

      #создание вирт окружения в директории test

      virtualenv test --no-site-packages -p /usr/local/bin/python


      # Чтобы активировать , необходимо выполнить (обратите
      # внимание на точку '.' перед вызовом activate -
      # вероятно, как раз ее вы и забыли указать)

      . test/bin/activate

      # после этого команда

      which python

      #должна показать , что дергается питон именно из окружения

      Тут же из консоли наберите 'python' и попробуйте выполнить 'import ' - должно сказать No module...

      Удалить
    3. Проблема было в том, что вызывал script.py вместо python script.py.

      Удалить
    4. ) А в первой строке , видимо, было /usr/bin/python ?

      Удалить
    5. Здравствуйте. Подскажите, что делать, у меня кофликтуют пакеты.
      http://paste.in.ua/8765/
      http://paste.in.ua/8766/

      Удалить
  4. Roman, а в какой директории вы находитесь и пытаетесь создать виртуальное окружение?

    IOError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/python_dateutil-2.1-py2.7.egg/EGG-INFO/top_level.txt'

    ОтветитьУдалить