python - virtuel - virtualenvwrapper




Activer un virtualenv via fabric en tant qu'utilisateur de déploiement (6)

C'est mon approche sur l'utilisation de virtualenv avec des déploiements locaux.

En utilisant le gestionnaire de contexte path() de fabric, vous pouvez lancer pip ou python avec des binaires de 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')

Je veux exécuter mon script Fabric localement, ce qui à son tour, connectez-vous à mon serveur, changez d'utilisateur à déployer, activez les projets .virtualenv, ce qui va modifier dir au projet et émettre un git pull.

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

J'utilise généralement la commande workon de virtualenvwrapper qui fournit le fichier activate et le fichier postactivate me place dans le dossier du projet. Dans ce cas, il semble que parce que le tissu s'exécute à partir de shell, le contrôle est donné à la structure, donc je ne peux pas utiliser la source de bash intégrée à '$ source ~ / .virtualenv / myvenv / bin / activate'

Quelqu'un at-il un exemple et une explication de la façon dont ils l'ont fait?


Comme une mise à jour de la prévision de bitprophet: Avec Fabric 1.0, vous pouvez utiliser prefix() et vos propres gestionnaires de contextes.

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

J'utilise simplement une fonction wrapper virtualenv () qui peut être appelée à la place de run (). Il n'utilise pas le gestionnaire de contexte cd, donc les chemins relatifs peuvent être utilisés.

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)

Merci à toutes les réponses postées et je voudrais ajouter une autre alternative pour cela. Il existe un module, fabric-virtualenv , qui peut fournir la fonction sous le même code:

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

fabric-virtualenv fait usage de fabric.context_managers.prefix , ce qui pourrait être un bon moyen :)


Voici un code pour un décorateur qui entraînera l'utilisation de l'environnement virtuel pour tout appel 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

et puis pour utiliser le décorateur, notez l'ordre des décorateurs est important:

@task
@with_venv
def which_python():
  "Gets which python is being used"
  run("which python")

virtualenvwrapper peut rendre cela un peu plus simple

  1. Utilisation de l'approche @ nh2 (cette approche fonctionne également lors de l'utilisation local , mais uniquement pour les installations virtualenvwrapper où workon est dans $PATH , en d'autres termes - 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. Ou déployez votre fichier fab et exécutez-le localement. Cette configuration vous permet d'activer virtualenv pour les commandes locales ou distantes. Cette approche est puissante car elle contourne local incapacité local à exécuter .bashrc en utilisant 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")
    






automated-deploy