문제

직물 스크립트를 로컬로 실행하고 싶습니다. 차례로 서버에 로그인하고 사용자를 배포하도록 전환하고 프로젝트를 활성화합니다.

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

일반적으로 virtualenvwrapper의 workon 명령을 사용하여 활성화 파일을 소스하면 postActivate 파일이 프로젝트 폴더에 넣습니다. 이 경우, 직물은 쉘 내에서 실행되기 때문에 제어가 패브릭으로 넘어 지므로 Bash의 소스 내장 '$ source ~/.virtualenv/myvenv/bin/activate'에 내장되어 있습니다.

누구든지 그들이 어떻게했는지에 대한 예와 설명이 있습니까?

도움이 되었습니까?

해결책

지금, 당신은 내가하는 일을 할 수 있습니다. Kludgy이지만 완벽하게 작동합니다* (이 사용법은 VirtualenVwrapper를 사용하고 있다고 가정합니다. , 그렇지 않은 경우) :

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

버전 1.0 이후로 Fabric은 다음과 같습니다 prefix 컨텍스트 관리자 이 기술을 사용하므로 예를 들어 다음과 같습니다.

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

* 사용하는 경우가 있습니다. command1 && command2 접근 방식은 언제와 같은 command1 실패 (command2 실행되지 않습니다) 또는 IF 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')

나는 단지 run () 대신 호출 할 수있는 간단한 래퍼 함수 virtualenv ()를 사용하고 있습니다. 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 can make this a little simpler

  1. Using @nh2's approach (this approach also works when using local, but only for virtualenvwrapper installations where workon is in $PATH, in other words -- 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. Or deploy your fab file and run this locally. This setup lets you activate the virtualenv for local or remote commands. This approach is powerful because it works around local's inability to run .bashrc using 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")
    

This is my approach on using virtualenv with local deployments.

Using fabric's path() context manager you can run pip or python with binaries from 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')

Thanks to all answers posted and I would like to add one more alternative for this. There is an module, fabric-virtualenv, which can provide the function as the same code:

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

fabric-virtualenv makes use of fabric.context_managers.prefix, which might be a good way :)

환경에 패키지를 설치하거나 환경에있는 패키지에 따라 명령을 실행하려면 복잡한 직물 메소드를 작성하거나 새로운 OS 패키지를 설치하는 대신 내 문제를 해결하기 위해이 해킹을 발견했습니다.

/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

이렇게하면 환경을 활성화 할 필요는 없지만 환경에서 명령을 실행할 수 있습니다.

다음은 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")

이 접근법은 저에게 효과적이었습니다. 당신도 이것을 적용 할 수 있습니다.

from fabric.api import run 
# ... other code...
def install_pip_requirements():
    run("/bin/bash -l -c 'source venv/bin/activate' "
        "&& pip install -r requirements.txt "
        "&& /bin/bash -l -c 'deactivate'")

가정합니다 venv 가상 Env Directory이며 적절한 경우이 방법을 추가하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top