通过Fabric在服务器上激活virtualenv时遇到问题

10 投票
5 回答
3982 浏览
提问于 2025-04-16 17:16

我正在尝试通过Fabric在我的测试服务器上运行一些Django管理命令。

问题是,Fabric似乎无法激活虚拟环境,因此在执行命令时使用的是系统自带的Python和库。

在服务器上,Django应用是通过虚拟环境运行的(不,我还没有使用virtualenvwrapper……)

使用Fabric(1.0.1)时,从我的电脑上运行的命令可能看起来像这样:

fabfile方法:

def collectstatic():
    require('settings', provided_by=[production, staging])

    with settings(warn_only=True):
        run('source %(env_path)s/bin/activate && python %(repo_path)s/%(project_name)s/configs/%(settings)s/manage.py collectstatic --noinput -v0' % env)

输出结果:

$ fab staging master collectstatic
[myserver.no] Executing task 'master'
[myserver.no] Executing task 'collectstatic'
[myserver.no] run: source /home/newsapps/sites/mysite/env/bin/activate && python /home/newsapps/sites/mysite/repository/mysite/configs/staging/manage.py collectstatic --noinput -v0
[myserver.no] Login password: 
[myserver.no] out: Unknown command: 'collectstatic'
[myserver.no] out: Type 'manage.py help' for usage.

我当然知道,Django命令collectstatic在1.3之前的版本是不存在的,这让我觉得正在使用的是系统自带的Python(它有Django 1.2)。

我的fabfile/项目结构是基于Tribapps团队的优秀fabfile

所以我创建了一个Fabric方法来测试Python版本:

def pythonver():
    require('settings', provided_by=[production, staging])

    with settings(warn_only=True):

    run('source %(env_path)s/bin/activate && echo "import sys; print sys.path" | python ' % env)

运行时,它给出的输出是:

$ fab staging master pythonver
[myserver.no] Executing task 'master'
[myserver.no] Executing task 'pythonver'
[myserver.no] run: source /home/newsapps/sites/mysite/env/bin/activate && echo "import sys; print sys.path" | python 
[myserver.no] Login password: 
[myserver.no] out: ['', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload', '/usr/lib/python2.6/dist-packages', '/usr/lib/pymodules/python2.6', '/usr/lib/pymodules/python2.6/gtk-2.0', 

如你所见,它使用的是系统自带的Python,而不是我位于home/newsapps/sites/mysite/env的虚拟环境。

但是如果我直接在服务器上运行这个命令:

source /home/newsapps/sites/mysite/env/bin/activate && echo "import sys; print sys.path" | python 

……那么它会输出虚拟环境的正确路径。

我到底做错了什么,为什么使用Fabric时命令没有用我的虚拟环境中的Python运行呢?

5 个回答

3

我也遇到过同样的问题。没能找到简单的解决办法。所以我直接用了虚拟环境里Python可执行文件的完整路径。我对Python不是很专业,但我觉得最后的结果是差不多的。我的fab文件里大概是这样的:

PYTHON = '/home/dudus/.virtualenvs/pai/bin/python'
PIP = '/home/dudus/.virtualenvs/pai/bin/pip'

def update_db():
    with cd(REMOTE_DIR + 'application/'):
        run('%s ./manage.py syncdb --settings="%s"' % 
            (PYTHON, SETTINGS)) # syncdb
        run('%s ./manage.py migrate --settings="%s"' % 
            (PYTHON, SETTINGS)) # south migrate
4

我建议你不用去激活虚拟环境,直接给出虚拟环境中Python解释器的完整路径就可以了。这样就能使用正确的PYTHONPATH等设置。

6

你应该从你的虚拟环境的bin目录里调用python版本,这样你就可以确保它使用的是虚拟环境里的python版本。

/home/newsapps/sites/mysite/env/bin/python /home/newsapps/sites/mysite/repository/mysite/configs/staging/manage.py collectstatic --noinput -v0

撰写回答