【问题标题】:Trouble activating virtualenv on server via Fabric无法通过 Fabric 在服务器上激活 virtualenv
【发布时间】:2011-05-09 08:33:05
【问题描述】:

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

问题是 Fabric 似乎无法激活 virtualenv,因此在执行命令时无法使用系统 python/libs。

在服务器上,Django 应用程序使用 virtualenv 运行(不,我还没有使用 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 之前的版本中不存在,这导致 med 认为系统 python(具有 Django 1.2)正在使用。

我的 fabfile/项目布局基于great fabfile of the Tribapps guys

所以我创建了一个fabric方法来测试pythonversion:

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 中的 virtualenv

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

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

.. 然后它从 virtualenv 输出正确的路径

我做错了什么,因为我的 virtualenv 中的 python 没有使用 Fabric 运行命令?

【问题讨论】:

    标签: python django virtualenv fabric


    【解决方案1】:

    你应该从你的 virtualenv bin 目录中调用 python 版本,然后你会确定它使用的是 virtualenv 的 python 版本。

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

    【讨论】:

    • @lajarre -v VERBOSITY, --verbosity=VERBOSITY 详细程度; 0=最小输出,1=正常输出,2=详细输出,3=非常详细输出
    【解决方案2】:

    我不会为激活 virtualenv 而烦恼,只需给出 virtualenv 的 python 解释器的完整路径即可。然后将使用正确的 PYTHONPATH 等。

    【讨论】:

    • 我正在我的 virtualenv 的 postactivate 文件中添加我的其他 PYTHONPATH 条目(例如您的项目的根目录)。我会假设这种方法不会添加它。我应该把这些放在别的地方吗?
    • 您可以将<name>.pth 文件添加到您的<virtualenv>/lib/python2.x/site-packages/ 目录中。这些可以包含将添加到您的PYTHONPATH 的路径。这是我部署过程的一部分。
    • 或者,您可以将您的项目制作成一个可安装的包(给它一个setup.py 文件),然后使用pip -e 安装它,这也是同样的事情。
    【解决方案3】:

    我遇到了同样的问题。不能用简单的方法解决。所以我只是使用了virtualenv中python bin文件的完整路径。我不是 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】:

      这将完美地工作:)

      from __future__ import with_statement
      from fabric.api import *
      from contextlib import contextmanager as _contextmanager
      
      env.hosts = ['servername']
      env.user = 'username' 
      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')
      

      【讨论】:

        【解决方案5】:

        这个方法对我有用,你也可以应用这个。

        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 是您的虚拟环境目录,并在适当的地方添加此方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-13
          • 1970-01-01
          • 1970-01-01
          • 2010-12-14
          • 2020-12-20
          • 1970-01-01
          • 2012-02-13
          相关资源
          最近更新 更多