Активировать виртуальное окружение через ткань, как развертывание пользовательских
Я хочу запустить свой сценарий структуры локально, который, в свою очередь, войдет в мой сервер, переключит пользователя на развертывание, активирует проекты .virtualenv, который изменит dir на проект и выдаст git pull.
def git_pull():
sudo('su deploy')
# here i need to switch to the virtualenv
run('git pull')
обычно я использую команду workon из virtualenvwrapper, которая создает файл activate, а файл postactivate помещает меня в папку проекта. В этом случае кажется, что, поскольку ткань работает изнутри оболочки, контроль передается ткани, поэтому я не могу используйте встроенный источник bash в '$source ~/.virtualenv / myvenv / bin / activate'
У кого-нибудь есть пример и объяснение того, как они это сделали?
8 ответов:
прямо сейчас вы можете делать то, что я делаю, что является kludgy, но работает отлично* (это использование предполагает, что вы используете virtualenvwrapper-который вы должны быть-но вы можете легко заменить в довольно длинном "исходном" вызове, который вы упомянули, если нет):
def task(): workon = 'workon myvenv && ' run(workon + 'git pull') run(workon + 'do other stuff, etc')
начиная с версии 1.0, ткань имеет
prefix
контекст менеджер, который использует эту технику, так что вы можете, например:def task(): with prefix('workon myvenv'): run('git pull') run('do other stuff, etc')
* обязательно будут случаи, когда с помощью
command1 && command2
подход может взорваться на вас, например, когдаcommand1
сбой (command2
никогда не будет работать) или еслиcommand1
не правильно бежал и содержит специальные символы оболочки, и так далее.
в качестве обновления для прогноза bitprophet: с Fabric 1.0 вы можете использовать префиксом() и ваши собственные менеджеры контекста.
from __future__ import with_statement from fabric.api import * from contextlib import contextmanager as _contextmanager env.hosts = ['servername'] env.user = 'deploy' env.keyfile = ['$HOME/.ssh/deploy_rsa'] env.directory = '/path/to/virtualenvs/project' env.activate = 'source /path/to/virtualenvs/project/bin/activate' @_contextmanager def virtualenv(): with cd(env.directory): with prefix(env.activate): yield def deploy(): with virtualenv(): run('pip freeze')
Я просто использую простую функцию-оболочку virtualenv (), которую можно вызвать вместо run (). Он не использует менеджер контекста cd, поэтому можно использовать относительные пути.
def virtualenv(command): """ Run a command in the virtualenv. This prefixes the command with the source command. Usage: virtualenv('pip install django') """ source = 'source %(project_directory)s/bin/activate && ' % env run(source + command)
virtualenvwrapper
можете сделать это немного проще
Используя подход @nh2 (этот подход также работает при использовании
local
, но только для установок virtualenvwrapper, гдеworkon
находится в$PATH
, другими словами -- Windows)from contextlib import contextmanager from fabric.api import prefix @contextmanager def virtualenv(): with prefix("workon env1"): yield def deploy(): with virtualenv(): run("pip freeze > requirements.txt")
или разверните файл fab и запустите его локально. Эта настройка позволяет активировать virtualenv для локальных или удаленных команд. Этот подход является мощным, потому что он работает вокруг
local
неспособность бежать.bashrc с помощьюbash -l
:@contextmanager def local_prefix(shell, prefix): def local_call(command): return local("%(sh)s \"%(pre)s && %(cmd)s\"" % {"sh": shell, "pre": prefix, "cmd": command}) yield local_prefix def write_requirements(shell="/bin/bash -lic", env="env1"): with local_prefix(shell, "workon %s" % env) as local: local("pip freeze > requirements.txt") write_requirements() # locally run("fab write_requirements")
Это мой подход к использованию
использование ткани!--7-->path () контекстный менеджер вы можете запуститьvirtualenv
с локальными развертываниями.pip
илиpython
с двоичными файлами из virtualenv.from fabric.api import lcd, local, path project_dir = '/www/my_project/sms/' env_bin_dir = project_dir + '../env/bin/' def deploy(): with lcd(project_dir): local('git pull origin') local('git checkout -f') with path(env_bin_dir, behavior='prepend'): local('pip freeze') local('pip install -r requirements/staging.txt') local('./manage.py migrate') # Django related # Note: previous line is the same as: local('python manage.py migrate') # Using next line, you can make sure that python # from virtualenv directory is used: local('which python')
Спасибо за все ответы, опубликованные, и я хотел бы добавить еще одну альтернативу для этого. Есть модуль, fabric-virtualenv, который может обеспечить функцию как такой же код:
>>> from fabvenv import virtualenv >>> with virtualenv('/home/me/venv/'): ... run('python foo')
fabric-virtualenv использует
fabric.context_managers.prefix
, что может быть хорошим способом :)
вот код для декоратора, который приведет к использованию виртуальной среды для любых вызовов run/sudo:
# This is the bash code to update the $PATH as activate does UPDATE_PYTHON_PATH = r'PATH="{}:$PATH"'.format(VIRTUAL_ENV_BIN_DIR) def with_venv(func, *args, **kwargs): "Use Virtual Environment for the command" def wrapped(*args, **kwargs): with prefix(UPDATE_PYTHON_PATH): return func(*args, **kwargs) wrapped.__name__ = func.__name__ wrapped.__doc__ = func.__doc__ return wrapped
и затем использовать декоратор, обратите внимание на порядок декораторов важно:
@task @with_venv def which_python(): "Gets which python is being used" run("which python")
Если вы хотите установить пакеты в среду или хотите запускать команды в соответствии с пакетами, которые у вас есть в среде, я нашел этот хак, чтобы решить мою проблему, вместо того, чтобы писать сложные методы fabric или устанавливать новые пакеты ОС:
/path/to/virtualenv/bin/python manage.py migrate/runserver/makemigrations # for running commands under virtualenv local("/home/user/env/bin/python manage.py migrate") # fabric command /path/to/virtualenv/bin/pip install -r requirements.txt # installing/upgrading virtualenv local("/home/user/env/bin/pip install -r requirements.txt") # fabric command
таким образом, вам может не понадобиться активировать среду, но вы можете выполнять команды в среде.