virtualenv是如何工作的?

63 投票
2 回答
20702 浏览
提问于 2025-04-17 07:57

我查看了activate这个脚本,感觉它主要做了两件事:

  • 设置一个叫做 VIRTUAL_ENV 的环境变量
  • 把 $VIRTUAL_ENV/bin 加到 PATH 的前面

virtualenv是怎么通过这些操作来提供神奇的虚拟环境的呢?我是不是漏掉了什么?

2 个回答

22
  1. 首先,用户使用命令 virtualenv myenv 创建一个新的虚拟环境。这会生成一个叫 myenv 的文件夹,并把系统的 Python 程序复制到 myenv/bin 目录下。同时,它还会在 myenv 中添加其他必要的文件和文件夹,包括一个在 bin/activate 的设置脚本,以及一个用于存放模块和包的 lib 子目录。
  2. 接着,用户通过 . myenv/bin/activate 来激活这个设置脚本,这样就会把命令行的 PATH 环境变量设置为以 myenv/bin 开头。
  3. 现在,当用户在这个命令行中运行 python 时,它会执行存储在 myenv/bin 中的那个 Python 程序。虽然这个程序和 /usr/bin/python 中的程序是一样的,但标准的 Python 程序会根据它自己的路径去查找包和模块(这个功能和虚拟环境没有关系)。它会在 ../lib/pythonX.Y 这个路径下查找,其中 X 和 Y 是 Python 程序的主版本号和次版本号。所以现在它会在 myenv/lib/pythonX.Y 中查找。
  4. 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

撰写回答