Python venv模块(三)——虚拟环境是什么

简单而言,Python虚拟环境是一个文件夹结构,它提供轻量且隔离的Python环境所需的一切。

(本文均以Linux系统为例)

一个文件夹结构

当使用venv模块创建虚拟环境时,Python创建一个自包含的文件夹,并复制或连接Python可执行文件到该文件夹结构下。

一个虚拟环境文件夹包含非常多的文件和文件夹,但是大部分都位于site-packages/文件夹下,如果将对应文件夹下的子文件夹和文件都忽略,则整体结构不算太冗长:

venv/
│
├── bin/
│   ├── Activate.ps1
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── pip
│   ├── pip3
│   ├── pip3.12
│   ├── python
│   ├── python3
│   └── python3.12
│
├── include/
│   │
│   └── python3.12/
│
├── lib/
│   │
│   └── python3.12/
│       │
│       └── site-packages/
│           │
│           ├── pip/
│           │
│           └── pip-24.2.dist-info/
│
├── lib64/
│   │
│   └── python3.12/
│       │
│       └── site-packages/
│           │
│           ├── pip/
│           │
│           └── pip-24.2.dist-info/
│
└── pyvenv.cfg
  • bin/包含虚拟环境的可执行文件。最值得注意的是 Python 解释器 (python) 和 pip 可执行文件 (pip),以及它们各自的符号链接(python3、python3.12、pip3、pip3.12)。该文件夹还包含虚拟环境的激活脚本。具体的激活脚本取决于使用的 shell。
  • include/是一个初始为空的文件夹,Python 用它来包含 C 头文件,以便安装依赖于 C 扩展的软件包。
  • lib/包含嵌套在指定 Python 版本 (python3.12/) 文件夹中的 site-packages/ 目录。虚拟环境中使用的外部软件包将安装在该文件夹中。从 Python 3.12 开始,虚拟环境只预装了一个依赖包 pip。
  • lib64:出于兼容性考虑,许多 Linux 系统中的lib64/都是以lib/的符号链接形式出现的。某些 Linux 系统可能会根据其体系结构使用lib/lib64/之间的区别来安装不同版本的库。
  • {name}-{version}.dist-info/pip的默认目录,包含软件包分发信息,用于记录已安装软件包的相关信息。
  • pyvenv.cfg是虚拟环境的关键文件。它只包含几个键值对,Python 使用它们来设置 sys 模块中的变量,这些变量决定了当前 Python 会话将使用哪个 Python 解释器和站点软件包目录。

总之,宏观而言,一个虚拟环境有三个主要部分:

  • Python二进制文件的副本或符号链接
  • pyvenv.cfg文件
  • site-packages目录

site-packages/内的安装包是可选的,但基本是默认存在的。即使该目录为空,虚拟环境仍然有效。

在默认设置下,venv 将只安装 pip,这是安装 Python 软件包的推荐工具,毕竟安装其他软件包是虚拟环境最常见的使用情况。

若Python版本<3.12,则site-packages/目录下会有一些额外的文件夹:

  • setuptools 模块: Python 打包生态系统中的基本工具。setuptools 扩展了 distutils 模块,提供了软件包发现、分发和依赖管理等功能。将 setuptools 作为默认设置可确保用户无需安装其他工具就能立即使用这些功能。在采用 PEP 517 和 PEP 518 之前,许多软件包都依赖 setuptools 进行安装。

  • _distutils_hack/ 模块确保 Python 在安装软件包时,选择本地的 ._distutils子模块而不是标准库的 distutils 模块。

  • pkg_resources/ 模块帮助应用程序自动发现插件,并允许 Python 软件包访问它们的资源文件。它与 setuptools 一起发布。

最后,还有一个名为 distutils-precedence.pth 的文件。该文件帮助设置 distutils 导入的路径优先级,并与 _distutils_hack 一起确保 Python 优先使用与 setuptools 捆绑的 distutils 版本,而不是内置版本。

若 Python 版本>=3.12,那么这些文件与文件夹不会预装在虚拟环境中。即使使用的是旧版本的 Python,也不需要记住它们就能有效地使用虚拟环境。

只需记住,在 site-packages/ 目录中预装的软件包都是标准工具,它们能让安装其他软件包变得更方便。

综上,Python虚拟环境只是一个文件架构,可以随时删除和重建。

隔离的Python安装

为构建一个隔离的环境以免安装的外部包与全局包冲突,venv重建了标准Python安装会创建的文件夹结构。

一个文件夹结构一节中指出的,该结构包括Python 二进制文件的副本或 symlink 的位置和 site-packages 目录(Python 安装外部软件包的目录)。

虚拟环境中的 Python 可执行文件是环境所基于的 Python 可执行文件的副本还是符号链接,主要取决于操作系统。

Windows 和 Linux 可能会创建符号链接而不是副本,而 macOS 则总是创建副本。可尝试在创建虚拟环境时使用可选参数来影响默认行为。在大多数情况下,这个问题没啥影响。

值得注意的是,Python标准库模块并未包含于虚拟环境文件夹结构下,但依然可以在虚拟环境调用。这是因为虚拟环境重用了用于创建虚拟环境的 Python 安装中的 Python 内置模块和标准库模块。

因为创建虚拟环境总是需要一个现有的 Python 安装,venv 选择重用现有的标准库模块,以避免将它们复制到新虚拟环境的开销。正如 PEP 405 的动机所述,这种有意为之的行为加快了虚拟环境的创建速度,并使其更加轻量级。

除了标准库模块外,你还可以在创建环境时通过参数让虚拟环境访问基本安装的软件包:

$ python3 -m venv venv/ --system-site-packages

如果在调用 venv 时添加 --system-site-packages,Python 将把 pyvenv.cfg 中 include-system-site-packages 的值设置为 true。这一设置意味着你可以使用安装到基本 Python 中的任何外部软件包,就像将它们安装到虚拟环境中一样。

这种连接是单向的。即使你允许虚拟环境访问源 Python 的 site-packages 文件夹,你安装到虚拟环境中的任何新包也不会与那里的包混合。Python 会尊重安装到虚拟环境中的软件包的隔离性,并将它们放到虚拟环境中独立的 site-packages 目录中。

总而言之,虚拟环境基本上就是一个带有设置文件的文件夹结构。它可能预装了 pip,也可能没有,它可以访问源 Python 标准库模块,同时保持隔离。

参考资源

Python Virtual Environments: A Primer – Real Python

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值