虚拟环境中使用了“--no-site-packages”和“pip”,但仍然找到全局安装的包?

153

我原本认为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的工作原理?


@SalemBenMabrouk 链接已损坏,这里是新链接。相关的Github问题:最近'--no-site-packages'标志消失了吗? - Ynjxsjmh
3
在那个链接中,它说 --no-site-packages 已被弃用,仅为向后兼容而保留。现在默认行为是 无法访问全局 site-packages。如果你想访问全局 site-packages,可以启用 --system-site-packages - Ynjxsjmh
从哪个版本开始被废弃了,@Ynjxsjmh? 我猜如果旧版本的python/virtualenv存在,我们仍然需要显式指定 --no-site-packages 吗? - Aaron McDaid
@AaronMcDaid 我没有深入研究这个问题,但我提到的github [issue](https://github.com/pypa/virtualenv/issues/1681)的作者说它至少在20.0.0中消失了。对于旧版本的virtualenv,我们仍然需要显式使用 --no-site-packages - Ynjxsjmh
15个回答

123

我曾经遇到了这样的问题,直到我意识到(在发现virtualenv之前很久),我将目录添加到了我的.bashrc文件中的PYTHONPATH变量。由于这发生在一年前,所以我没有马上想到。


18
我的英雄!如果你只是想快速检查一下是否存在问题,可以运行 printenv 命令来查看 PYTHONPATH 是否存在。如果存在,运行 unset PYTHONPATH 命令。如果你不想再遇到这个问题,那么你仍然需要找到问题所在的位置,但这样可以让你在当前的 shell 会话中重新设置虚拟环境。 - UltraBob
1
我希望我能给你更多的赞。在遇到因为我的PYTHONPATH已经设置而出现的问题后,我不止一次来到了这个页面。 - Bemmu
我知道这是一个非常(非常)老的帖子,但我已经到处搜索过了,包括在SO上提问自己的问题,但我无法弄清如何让 --no-site-packages 生效。我接近放弃,想看看是否可以清除 Ubuntu 并查看是否可以解决问题。最初我以为我遇到了相同的 PYTHONPATH 问题,但在运行 printenv 后,我看不到它。挫败感正在增加,非常感谢任何帮助。通过使用 --no-site-packages 创建的 venv 中的 sys.path 似乎包含所有我的包目录。我一点也不知道如何修改它。求助? - NotAnAmbiTurner
1
如果你需要在虚拟环境之外查找可执行文件,这也同样适用于全局的 PATH 变量。 - enderland
在获取 pip freeze 的软件包列表之前,确保您也激活了新环境。否则,您将获得全局软件包列表,而不是新环境中的软件包列表。(请参见 finspin 的答案。) - user3062149
显示剩余3条评论

31

您必须确保在创建的虚拟环境中运行 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


我也遇到了同样的问题。我不知道它是怎么发生的,因为一开始调用pip freeze时显示了正确的软件包,但几天后它开始调用位于/usr/local/bin/的软件包... - jimijazz
1
这是我的问题:我将 pip 别名设置为全局 pip 的特定路径,当激活虚拟环境时未被覆盖。 - merlinND
1
你刚刚救了我,这对我很有效(pip3和python3.7) 谢谢 - Saed Yousef

24

最终我发现,不管出于什么原因,pip -E 都不起作用。然而,如果我激活虚拟环境并使用由 virtualenv 提供的 easy_install 安装 pip,然后直接在其中使用 pip,它看起来就像预期的那样工作,并且只显示虚拟环境中的软件包。


2
就我个人而言,使用当前的 pip 和 virtualenv 版本,您原来的工作流程现在已经可以正常运行了。尽管如此,我仍然避免使用 -E 选项,并在每个虚拟环境中单独安装 pip。 - Carl Meyer

20

使用以下命令暂时清除 PYTHONPATH

```bash export PYTHONPATH= ```
export PYTHONPATH=

然后创建并激活虚拟环境:

virtualenv foo
. foo/bin/activate

只有这样:

pip freeze

通过调用unset PYTHONPATH并立即创建venv来临时清理PYTHONPATH是有帮助的。 - Miroslav Radojević

19
我知道这是一个非常古老的问题,但对于那些寻找解决方案的人来说:
在运行pip freeze之前,不要忘记激活虚拟环境source bin/activate)。否则,您将得到所有全局包的列表。请注意保留HTML标签。

正确的答案是:在初始化虚拟环境后,您必须激活它,否则将使用系统版本的Python。 - AsAP_Sherb

16

--no-site-packages 顾名思义,会从 sys.path 中移除标准的 site-packages 目录。其他位于标准 Python 路径下的内容仍将保留。


3
еҜ№жҲ‘жқҘиҜҙпјҢдҪҝз”Ёexport PYTHONPATH=жё…зҗҶжҲ‘зҡ„PYTHONPATHдјјд№Һиө·дәҶдҪңз”ЁгҖӮ - juniper-
1
通过取消 PYTHONPATH 清理后,使用 python3 -m venv ./venv_dir 将启动虚拟环境。只是 --no-site-packages 选项未被识别。一旦激活了 venv,pip freeze 将列出一个干净的虚拟环境的软件包。 - Miroslav Radojević

5
如果在Windows上直接调用script.py脚本,会出现类似的问题,这会使用Windows默认打开程序并在虚拟环境之外打开Python。如果使用python script.py进行调用,则将使用虚拟环境内的Python。

脚本顶部应该有一个 shebang 行(以“!#”开头),它将指向要使用的解释器。 - wobbily_col

3
这种情况似乎也会发生在你将virtualenv目录移动到另一个目录(在Linux上),或重命名父目录的情况下。

1

virtualenv pip无法工作的可能原因之一是其任何父文件夹的名称中包含空格,将其重命名为/Documents/projectName/app即可解决问题。


1
我遇到了同样的问题。对我来说(在Ubuntu上),问题是我的路径名包含$。当我在$ dir之外创建虚拟环境时,它可以正常工作。
奇怪。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接