2009-07-24 6 views
123

Я хочу запустить локальный скрипт моей сети, который, в свою очередь, войдет в мой сервер, переключит пользователя на развертывание, активирует проекты .virtualenv, что изменит каталог на проект и выпустят тянуть гит.Активировать virtualenv через тканью как пользователь развертывания

def git_pull(): 
    sudo('su deploy') 
    # here i need to switch to the virtualenv 
    run('git pull') 

Я обычно использую команду workon из virtualenvwrapper, какие источники файл реактивировать и postactivate файл поместит меня в папке проекта. В этом случае кажется, что из-за того, что ткань работает изнутри оболочки, управление передается в ткань, поэтому я не могу использовать встроенный источник bash для '$ ​​source ~/.virtualenv/myvenv/bin/activate'

У кого-нибудь есть пример и объяснение того, как они это сделали?

+1

Из любопытства, почему Арен» t вы используете 'workon' как' префикс'? –

ответ

93

Прямо сейчас вы можете делать то, что я делаю, что kludgy, но прекрасно работает * (это использование предполагает, что вы используете virtualenvwrapper - что вам нужно - но вы можете легко заменить его на более длинный источник 'называют вы упомянули, если нет):

def task(): 
    workon = 'workon myvenv && ' 
    run(workon + 'git pull') 
    run(workon + 'do other stuff, etc') 

Начиная с версии 1.0, ткань имеет prefix context manager, который использует эту технику, так что вы можете, например:

def task(): 
    with prefix('workon myvenv'): 
     run('git pull') 
     run('do other stuff, etc') 

* Бывают случаи, когда использование вами подхода command1 && command2 может взорвать вас, например, когда command1 сбой (command2 никогда не будет запущен) или если command1 не экранирован надлежащим образом и содержит специальные символы оболочки и т. Д.

+7

Но 'workon' неизвестен' sh'. Как мы можем сказать, что ткань использует bash вместо этого? –

+16

IMHO вы должны просто использовать 'source venv/bin/activate'. Это проще и работает из коробки. «workon» - это дополнительная зависимость, и даже если он установлен, вам нужно добавить его в '.bashrc' - слишком сложное для развертывания в сети. –

+0

@PierredeLESPINAY см. Http://stackoverflow.com/questions/11272372/invoking-bash-aliases-in-fabric-scripts для решения вашей проблемы. – dukebody

17

Я просто использую простую функцию-оболочку 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) 
131

как обновление прогноза bitprophet в: С Ткань 1,0 Вы можете использовать prefix() и собственных менеджеров контекста.

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') 
+5

См. Http://readthedocs.org/docs/fabric/latest/api/core/context_managers.html – tobych

+3

contextmanager делает его очень элегантным – ashwoods

+6

См. Также: https://pypi.python.org/pypi/fabric-virtualenv –

8

virtualenvwrapper может сделать это немного проще

  1. Используя подход @ 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") 
    
  2. Или разверните файл fab и запустите эту локаль у. Эта настройка позволяет вам активировать virtualenv для локальных или удаленных команд. Такой подход является мощным, поскольку он работает вокруг local «s неспособность работать .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") 
    
+0

Благодарим за обобщение ответа nh2. Объявление virtualenv contextmanager может быть выполнено в 5 строках на Python 2.6+, однако никогда не гарантируется, что псевдоним «workon» всегда импортируется правильно, и гораздо надежнее использовать 'source .../activate 'command –

+0

Спасибо, @contextmanager - это то, что я ищу. –

7

Это мой подход по использованию 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') 
+0

Мне это очень нравится - я не вижу никаких очевидных недостатков в этом подходе, и это очень чисто. Спасибо :) – simon

+0

по-прежнему лучший и самый чистый ответ здесь – grafa

0

Вот код для декоратора, который приведет к использованию виртуальной среды для любой работы/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") 
4

Спасибо всем, что ответили, и я хотел бы добавить еще одну альтернативу для этого. Существует модуль, fabric-virtualenv, который может обеспечить функцию как тот же код:

>>> from fabvenv import virtualenv 
>>> with virtualenv('/home/me/venv/'): 
...  run('python foo') 

ткань-virtualenv делает использование fabric.context_managers.prefix, что может быть хорошим способом :)

 Смежные вопросы

  • Нет связанных вопросов^_^