Activate a virtualenv via fabric as deploy user
As an update to bitprophet's forecast: With Fabric 1.0 you can make use of prefix() and your own context managers.
from __future__ import with_statementfrom fabric.api import *from contextlib import contextmanager as _contextmanagerenv.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'@_contextmanagerdef virtualenv(): with cd(env.directory): with prefix(env.activate): yielddef deploy(): with virtualenv(): run('pip freeze')
Right now, you can do what I do, which is kludgy but works perfectly well* (this usage assumes you're using virtualenvwrapper -- which you should be -- but you can easily substitute in the rather longer 'source' call you mentioned, if not):
def task(): workon = 'workon myvenv && ' run(workon + 'git pull') run(workon + 'do other stuff, etc')
Since version 1.0, Fabric has a prefix
context manager which uses this technique so you can for example:
def task(): with prefix('workon myvenv'): run('git pull') run('do other stuff, etc')
* There are bound to be cases where using the command1 && command2
approach may blow up on you, such as when command1
fails (command2
will never run) or if command1
isn't properly escaped and contains special shell characters, and so forth.
I'm just using a simple wrapper function virtualenv() that can be called instead of run(). It doesn't use the cd context manager, so relative paths can be used.
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)