python - descargar - Activar un virtualenv vía fabric como usuario de implementación
virtualenv install (8)
Quiero ejecutar mi script de tejido localmente, que a su vez, iniciar sesión en mi servidor, cambiar de usuario para implementar, activar los proyectos .virtualenv, que cambiará dir al proyecto y emitirá un git pull.
def git_pull():
sudo(''su deploy'')
# here i need to switch to the virtualenv
run(''git pull'')
Normalmente utilizo el comando workon de virtualenvwrapper que origina el archivo de activación y el archivo postactivate me pondrá en la carpeta del proyecto. En este caso, parece que debido a que el tejido se ejecuta desde dentro del caparazón, el control se cede al tejido, por lo que no puedo usar la fuente de bash incorporada en ''$ source ~ / .virtualenv / myvenv / bin / activate''
¿Alguien tiene un ejemplo y una explicación de cómo lo han hecho?
Aquí hay un código para un decorador que dará como resultado el uso del entorno virtual para cualquier llamada 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
y luego para usar el decorador, tenga en cuenta que el orden de los decoradores es importante:
@task
@with_venv
def which_python():
"Gets which python is being used"
run("which python")
Como una actualización del pronóstico de bitprophet: con Fabric 1.0 puede usar prefix() y sus propios administradores de contexto.
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'')
En este momento, puedes hacer lo que hago, que es kludgy pero funciona perfectamente * (este uso asume que estás usando virtualenvwrapper, que deberías serlo), pero puedes sustituirlo fácilmente en la llamada ''fuente'' más larga que mencionaste , si no):
def task():
workon = ''workon myvenv && ''
run(workon + ''git pull'')
run(workon + ''do other stuff, etc'')
Desde la versión 1.0, Fabric tiene un administrador de contexto de prefix
que usa esta técnica para que pueda, por ejemplo:
def task():
with prefix(''workon myvenv''):
run(''git pull'')
run(''do other stuff, etc'')
* Es probable que command1 && command2
casos en los que el uso del método command1 && command2
pueda explotar, como cuando command1
falla ( command2
nunca se ejecutará) o si command1
no se escapó correctamente y contiene caracteres de shell especiales, y así sucesivamente.
Este es mi enfoque sobre el uso de virtualenv
con implementaciones locales.
Utilizando el gestor de contexto path() fabric puede ejecutar pip
o python
con binarios 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'')
Gracias a todas las respuestas publicadas y me gustaría agregar una alternativa más para esto. Hay un módulo, fabric-virtualenv , que puede proporcionar la función como el mismo código:
>>> from fabvenv import virtualenv
>>> with virtualenv(''/home/me/venv/''):
... run(''python foo'')
fabric-virtualenv hace uso de fabric.context_managers.prefix
, que podría ser una buena manera :)
Si desea instalar los paquetes en el entorno o desea ejecutar comandos de acuerdo con los paquetes que tiene en el entorno, he encontrado este truco para resolver mi problema, en lugar de escribir métodos complejos de estructura o instalar nuevos paquetes de SO:
/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
De esta manera es posible que no necesite activar el entorno, pero puede ejecutar comandos en el entorno.
Solo estoy usando una función de envoltura simple virtualenv () a la que se puede llamar en lugar de ejecutar (). No utiliza el administrador de contexto de CD, por lo que se pueden usar rutas relativas.
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
puede hacer esto un poco más simple
Usar el enfoque de @ nh2 (este enfoque también funciona cuando se usa
local
, pero solo para instalaciones virtualenvwrapper dondeworkon
está en$PATH
, en otras palabras, 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")
O despliega tu archivo fab y ejecútalo localmente. Esta configuración le permite activar virtualenv para comandos locales o remotos. Este enfoque es poderoso porque funciona en función de la incapacidad
local
para ejecutar .bashrc utilizandobash -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")