virtualenv --no-site-packages 和 pip 仍然找到全局包?

153 投票
15 回答
126992 浏览
提问于 2025-04-15 14:05

我原以为使用 virtualenv --no-site-packages 可以创建一个完全独立的Python环境,但似乎并不是这样。

举个例子,我在全局环境中安装了python-django,但我想创建一个虚拟环境,里面有不同版本的Django。

$ virtualenv --no-site-packages foo       
New python executable in foo/bin/python
Installing setuptools............done.
$ pip -E foo install Django
Requirement already satisfied: Django in /usr/share/pyshared
Installing collected packages: Django
Successfully installed Django

根据我的理解,上面的 pip -E foo install 是用来重新安装一个新的Django版本的。而且,如果我让pip列出环境中的包,我会看到很多包。我本以为在使用了 --no-site-packages 的新环境中,这个列表应该是空的吧?

$ pip -E foo freeze
4Suite-XML==1.0.2
BeautifulSoup==3.1.0.1
Brlapi==0.5.3
BzrTools==1.17.0
Django==1.1
... and so on ...

我是不是对 --no-site-packages 的工作原理理解错了?

15 个回答

24

最后我发现,不管是什么原因,pip -E这个命令并没有起作用。不过,如果我先激活虚拟环境,然后用虚拟环境里提供的easy_install来安装pip,再直接在这个环境里使用pip,似乎就能正常工作,只显示虚拟环境里的包。

32

你需要确保你在你创建的虚拟环境中运行 pip,而不是全局环境中的那个。

env/bin/pip freeze

来看一个测试:

我们使用 --no-site-packages 选项来创建虚拟环境:

$ virtualenv --no-site-packages -p /usr/local/bin/python mytest
Running virtualenv with interpreter /usr/local/bin/python
New python executable in mytest/bin/python
Installing setuptools, pip, wheel...done.

然后我们检查新创建的 pipfreeze 输出:

$ mytest/bin/pip freeze
argparse==1.3.0
wheel==0.24.0

但是如果我们使用全局的 pip,结果就会是这样:

$ pip freeze
...
pyxdg==0.25
...
range==1.0.0
...
virtualenv==13.1.2

也就是说,这里列出了 pip 在整个系统中安装的所有包。通过检查 which pip,我们可以看到(至少在我的情况下)得到的结果是类似 /usr/local/bin/pip 的路径,这意味着当我们运行 pip freeze 时,它调用的是这个全局的二进制文件,而不是 mytest/bin/pip

123

我之前也遇到过类似的问题,直到我意识到(在我发现virtualenv之前很久),我已经在我的.bashrc文件里添加了一些目录到PYTHONPATH里。因为那是超过一年前的事了,所以我当时没有立刻想到这一点。

撰写回答