virtualenv是如何工作的?
我查看了activate这个脚本,感觉它主要做了两件事:
- 设置一个叫做 VIRTUAL_ENV 的环境变量
- 把 $VIRTUAL_ENV/bin 加到 PATH 的前面
那virtualenv
是怎么通过这些操作来提供神奇的虚拟环境的呢?我是不是漏掉了什么?
2 个回答
22
- 首先,用户使用命令
virtualenv myenv
创建一个新的虚拟环境。这会生成一个叫 myenv 的文件夹,并把系统的 Python 程序复制到 myenv/bin 目录下。同时,它还会在 myenv 中添加其他必要的文件和文件夹,包括一个在 bin/activate 的设置脚本,以及一个用于存放模块和包的 lib 子目录。 - 接着,用户通过
. myenv/bin/activate
来激活这个设置脚本,这样就会把命令行的PATH
环境变量设置为以 myenv/bin 开头。 - 现在,当用户在这个命令行中运行
python
时,它会执行存储在 myenv/bin 中的那个 Python 程序。虽然这个程序和 /usr/bin/python 中的程序是一样的,但标准的 Python 程序会根据它自己的路径去查找包和模块(这个功能和虚拟环境没有关系)。它会在 ../lib/pythonX.Y 这个路径下查找,其中 X 和 Y 是 Python 程序的主版本号和次版本号。所以现在它会在 myenv/lib/pythonX.Y 中查找。 - myenv/bin 目录里还有一个叫
pip
的脚本,这样当用户在虚拟环境中使用 pip 安装新包时,这些包会被安装到 myenv/lib/pythonX.Y 中。
61
我来简单说一下这个基本过程,这是我从@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
。