26

所以每个人都告诉我使用 pip 和 virtualenv ,但没有人能够向我解释它比我目前的方法更好。人们使用 pip 和 virtualenv 的主要原因似乎是其他人都在使用它......

我确信使用 PIP 和 virtualenv 有很好的理由,但我无法通过 Google 找到它们。我希望来自 stackoverflow 社区的人能够向我解释它们。

以下是我目前组织 Django 项目的方式:

site/src/ : contains all python-only dependencies of my project

site/lib/ : contains symlinks to the python packages

site/[projectname]/ : contains all my project specific code

整个站点文件夹都在我的存储库中检入(是的,包括所有仅 python 的依赖项,例如 django 本身)。

所有非仅 python 的依赖项(PIL、psycopg2、...)都记录在自述文件中并安装在系统级别(apt-get install ....)

例如,假设我有一个项目名称“projectfoo”,它依赖于 django-1.2.3、pygeoip-0.1.3 和 psycopg2,我将拥有:

/usr/lib/python2.5/site-packages/psycopg2

~/projects/foo/site : checkout of my repository
~/projects/foo/site/src/django-1.2.3
~/projects/foo/site/src/pygeoip-0.1.3
~/projects/foo/site/lib/django -> symlink to ../src/django-1.2.3/django
~/projects/foo/site/lib/pygeoip -> symlink to ../src/pygeoip-0.1.3/pygeoip
~/projects/foo/site/projectfoo/

现在在实践中这与 PIP/virtualenv 相比如何?

用我目前的方法部署项目

svn checkout https://myserver.com/svn/projectfoo/tags/1.0.0STABLE/site

使用 PIP/virtualenv 部署

wget https://myserver.com/svn/projectfoo/tags/1.0.0STABLE/projectfoo-requirements.txt
pip install -U -E projectfoo-venv -r projectfoo-requirements.txt

用我目前的方法处理一个项目

cd ~/projects/foo/site/projectfoo
export PYTHONPATH=.:..:../lib
./manage.py runserver 0:8000

使用 PIP/virtualenv 处理项目

workon projectfoo
cd path/to/project
./manage.py runserver 0:8000

处理非仅 python 依赖项

非python-only依赖项将以相同的方式处理,我无法使用--no-site-packagesvirtualenv 选项并在我的服务器上安装编译器和所有构建依赖项,我认为实际上没有人这样做反正。

使用我当前的方法升级仅 python 的依赖项

我在 src 中签出/解压缩新版本,从 src 中删除旧版本,更新 lib 中的符号链接并提交。现在从事该项目的其他所有人都将在他们的下一个svn upgit pull. 不好的一件事是,如果 src 中的旧文件夹包含一些 pyc 文件,它将保留,这可以通过在更新本地副本之前删除所有 pyc 轻松避免。

使用 PIP/virtualenv 升级仅 python 的依赖项

您提交了一个新版本的需求文件,希望每个参与该项目的人在更新本地副本并运行pip install -E projectfoo-venv -r requirements.txt.

编辑:我在 pip 中删除了 -U 的使用,这在 pip 8.2 中不需要

编辑:与我目前的方法相比,pip/virtualenv 的唯一优势似乎是当您处理需要不同版本的 python 的不同项目时。但是根据我的经验,当你需要不同版本的 python 时,你还需要不同版本的其他系统库(PIL、psycopg2、...),而 virtualenv 对此无济于事(除非你足够疯狂地使用 -- no-site-package 选项,即使那样它也不完整)。对于这种情况,我能想到的唯一解决方案是使用不同的虚拟机。

那么我错过了什么?有人可以指出一个 PIP 或 virtualenv 比我正在做的更好的用例吗?

4

4 回答 4

19

当您有多个项目并且不希望它们都共享相同的 Python 安装时,virtualenv 真的很出色。例如,您可能有两个需求冲突的项目。

于 2010-12-19T16:52:35.847 回答
9

“所有非仅python依赖项(PIL,psycopg2,...)都记录在自述文件中并安装在系统级别(apt-get install ....)”

那么你不能对不同的项目有不同的依赖,也不能对不同的项目有不同版本的这些依赖。

这样做的一个影响是您的本地安装不能准确地反映生产机器,因此您可能在重现生产错误时遇到问题,例如。

如果您安装需要一个版本的系统工具,您将被迫在任何地方使用相同的版本,这可能会破坏您的项目。

此外,需要在系统 python 级别上完成取消删除模块。Virtualenv 意味着您可以设置 python 安装来测试东西,而不会污染系统安装。

我绝对建议为您的项目使用单独的 python,并使用将 Python 与项目隔离的东西,例如 virtualenv 或 zc.buildout。

PIP 只是安装模块的一种更简单的方法,它还可以帮助您卸载它们。

“我不可能使用 virtualenv 的 --no-site-packages 选项并在我的服务器上安装编译器和所有构建依赖项,我认为实际上没有人在这样做。”

不,我使用 zc.buildout,但它的作用大致相同,但工作量更少。;)

于 2010-12-19T16:55:21.790 回答
3

对于我通常的项目,我遵循您建议的方法,而不使用 pip/virtualenv。 这允许我将包放在特定的目录中。

+ext
  |
  |------python packages
+source
  |
  |------ project code and packages

通常在启动脚本中我更新 PYTHONPATH

export PYTHONPATH="";
export PYTHONPATH="${PYTHONPATH}:${workingdir}/path/to/ext";

这具有保持项目和依赖项自包含的优点。我附和,你的想法在这里。

但是,我发现使用 virtualenv,当

  1. 我必须尝试something new.
  2. two different versions of package当我想使用和比较它们时更好。
  3. 另一个用途是,我保存在哪里different related packages that can be used across projects

例如:文档:我安装的一些关键包包括 sphinx、pygraphwiz、nterworkX 和一些更多的可视化包。我在项目中使用它,并且将它排除在系统级安装之外,以保持它不受污染。

我也想让你结帐:蛋黄。我觉得结合 pip/virtualenv 很好。

您可以列出包

yolk -l
Jinja2          - 2.5.5        - active 
Markdown        - 2.0.3        - active 
Pycco           - 0.1.2        - active 
......

并查看 pypi 更新。

yolk --show-updates
Pycco 0.1.2 (0.2.0)
Sphinx 1.0.4 (1.0.5)
pip 0.8.1 (0.8.2)
于 2010-12-19T16:59:50.147 回答
2

使用 PIP/virtualenv 部署:

照你说的:

wget https://myserver.com/svn/projectfoo/tags/1.0.0STABLE/projectfoo-requirements.txt
pip install -U -E projectfoo-venv -r projectfoo-requirements.txt

我做什么:我也“冻结”包,但我用pipandvirtualenv来检查整个项目;包括 Python 包。所以我的部署和你的完全一样:

svn checkout https://myserver.com/svn/projectfoo/tags/1.0.0STABLE/site

使用 PIP/virtualenv 处理项目:

照你说的:

workon projectfoo
cd path/to/project
./manage.py runserver 0:8000

我做什么:添加一个postactivate 钩子,如下所示:

$ cat bin/postactivate
cd $VIRTUAL_ENV
./manage.py runserver 0:8000
$

现在,更改为项目:

workon projectfoo
于 2010-12-19T18:18:08.270 回答