pip和virtualenv有什么好处?
大家都在告诉我使用 pip 和 virtualenv,但没有人能解释这比我现在的做法好在哪里。大家使用 pip 和 virtualenv 的主要原因似乎就是因为大家都在用它……
我相信使用 pip 和 virtualenv 有很好的理由,但我在谷歌上找不到这些理由。我希望 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 等)都在 README 文件中记录,并在系统级别安装(用 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 依赖的东西处理方式是一样的,我绝对不会使用 virtualenv 的 --no-site-packages
选项,并在我的服务器上安装编译器和所有构建依赖,我觉得没有人会这么做。
用我现在的方式升级 Python 依赖:
我会在 src 目录下检出/解压新版本,删除旧版本,更新 lib 中的符号链接,然后提交。这样,其他所有在这个项目上工作的人在下次 svn up
或 git pull
时就能得到更新。有一点不太好的就是,如果 src 中的旧文件夹里有 pyc 文件,它会保留,这可以通过在更新本地副本之前删除所有 pyc 文件来避免。
用 PIP/virtualenv 升级 Python 依赖:
你提交一个新的 requirements 文件版本,希望项目中的每个人在更新本地副本时能注意到新版本,然后他们运行 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 个回答
我按照你建议的方法,不使用pip或virtualenv来处理我的常规项目。 这样我可以把软件包放在特定的目录里。
+ext
|
|------python packages
+source
|
|------ project code and packages
通常在启动脚本中,我会更新PYTHONPATH。
export PYTHONPATH="";
export PYTHONPATH="${PYTHONPATH}:${workingdir}/path/to/ext";
这样做的好处是可以让项目和依赖关系保持在一个封闭的环境中。我非常赞同你的想法。
不过,我发现使用virtualenv的情况是:
- 当我需要尝试一些
新东西
的时候。 - 更好的是,当我想使用
两个不同版本的软件包
并进行比较时。 - 还有一种情况是,我会把
不同相关的软件包放在一起,这样可以在多个项目中使用
。
例如:文档:我安装的一些关键软件包包括sphinx、pygraphwiz、nterworkX和一些其他可视化软件包。我在多个项目中使用这些软件包,并且把它们放在系统级别的安装之外,以保持环境的干净。
我还想让你看看:Yolk。 我觉得它和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)
"所有非仅限Python的依赖项(比如PIL、psycopg2等)都在README中有说明,并且是在系统级别安装的(比如用apt-get install ....)"
这样的话,你就不能为不同的项目使用不同的依赖项,也不能为不同的项目使用这些依赖项的不同版本。
这会导致一个问题,就是你本地安装的环境和生产环境(实际运行的环境)不一致,这样你在复现生产环境中的错误时可能会遇到麻烦。
如果你安装了一些系统工具,它们需要某个特定版本的依赖项,那么你就只能在所有地方都使用这个版本,这可能会导致你的项目出现问题。
另外,想要恢复被删除的模块,必须在系统的Python环境中进行。使用虚拟环境(virtualenv)可以让你设置一个独立的Python环境来测试东西,而不会影响到系统的Python安装。
我强烈建议为你的项目使用一个独立的Python环境,并使用一些工具来进一步隔离这个Python环境,比如virtualenv或zc.buildout。
PIP只是一个更简单的安装模块的方式,同时也能帮助你卸载模块。
"我绝对不想在我的服务器上使用virtualenv的--no-site-packages选项,还要安装编译器和所有构建依赖,我觉得没人会真的这么做。"
不,我使用zc.buildout,但其实效果差不多,只是工作量更少。;)
当你有很多项目时,virtualenv 就特别好用,因为它可以让每个项目使用不同的 Python 环境,而不是让它们都共享同一个 Python 安装。比如说,你可能有两个项目,它们对 Python 的要求不一样,这时候就会出现冲突。