虚拟环境是如何工作的?

62

我检查了activate脚本,它只做了以下几件事:

  • 设置VIRTUAL_ENV环境变量
  • 在PATH前面添加$VIRTUAL_ENV/bin

virtualenv是如何通过这些步骤提供神奇的虚拟环境的?我错过了什么吗?


3
不要忘记 virtualenv burrito。它是一个很有用的工具,可以帮助你更方便地管理Python虚拟环境。 - maček
2个回答

60

我将描述基本过程,这些内容来自@jcollado链接的演示文稿。

当Python启动时,它会查看二进制文件的路径及其前缀。

假设您的虚拟环境为/home/blah/scratch。Python进程知道它是从/home/blah/scratch/bin/python执行的(通常只是系统Python二进制文件/usr/bin/python的副本),并且它知道自己的版本X.Y,因为它被编译到其中。然后Python按以下顺序查找lib/pythonX.Y/os.py

/home/blah/scratch/bin/lib/pythonX.Y/os.py
/home/blah/scratch/lib/pythonX.Y/os.py    <-- this file should exist
/home/blah/lib/pythonX.Y/os.py
/home/lib/pythonX.Y/os.py
/lib/pythonX.Y/os.py

它停在/home/blah/scratch/lib/pythonX.Y/os.py,因为这是实际存在的第一个文件。如果不存在,Python将继续寻找。然后,它基于此设置sys.prefix。它使用类似的过程来设置sys.exec_prefix,然后根据这些构建sys.path


1
X.X源自Python版本,因此它将是2.7或类似版本。 - Max
从未想过通过 sys.prefix 发现这条路径! - Drake Guan
3
感谢您在回答中清晰地解释,而不是链接到可能会在未来更改或消失的外部来源。 - Josh Sherick
在回答之前,哪里有说明所有这些的文档?即使是这个也很难找到。 - Gulzar

22
  1. 首先,用户使用命令 virtualenv myenv 创建一个新的虚拟环境。这将创建一个名为myenv的目录,并将系统 Python 二进制文件复制到myenv/bin中。它还会在myenv中添加其他必要的文件和目录,包括bin/activate中的设置脚本和一个子目录lib,用于存放模块和软件包。
  2. 随后,用户使用命令. myenv/bin/activate 来激活脚本,这将把shell的PATH环境变量设置为以myenv/bin开头。
  3. 现在,当用户从该shell运行python时,它将执行存储在myenv/bin中的二进制文件副本。即使该二进制文件与/usr/bin/python中的文件相同,但标准的Python二进制文件设计为搜索相对于二进制文件路径的目录中的软件包和模块 (此功能与 virtualenv 无关)。 它在../lib/pythonX.Y中查找,其中X和Y是Python二进制文件的主版本号和次版本号。现在,它正在查找myenv/lib/pythonX.Y目录下的组件。
  4. myenv/bin目录还包含一个名为pip的脚本,以便当用户使用虚拟环境中的pip安装新软件包时,它们将被安装在myenv/lib/pythonX.Y中。

2
我想知道你们是从哪里得知类似于 ../lib/pythonX.Y 这样的秘密路径,以及其他与 sys.prefix 相关的内容? - Drake Guan
2
我还没有看到任何关于它的好文档,但是在构建Python源代码时,我注意到了这种行为。您也可以像这样测试它:mkdir /tmp/bin; mkdir /tmp/lib; cp /usr/bin/python /tmp/bin; cp -r /usr/lib/pythonX.Y/ /tmp/lib/pythonX.Y; /tmp/bin/python。然后输入 import sys; sys.prefix。这将显示“/tmp”。如果您删除/tmp/lib目录,则会恢复为“/usr”。 - clark800
2
第三步是我所缺失的关键--即Python二进制文件在其可执行文件所在的目录中查找相关文件。谢谢。 - Dave X

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