您是否考虑过虚拟环境库如何在Python中工作? 在本文中,我建议熟悉所有环境库都使用的主要概念,例如virtualenv,virtualenvwrapper,conda,pipenv。
最初,在Python中没有内置的创建环境的功能,并且此功能是作为hack实现的。 事实证明,所有库都基于python解释器的一个非常简单的功能。
当Python启动解释器时,它将开始查找包含模块(站点程序包)的目录。 搜索从有关解释程序可执行文件(python.exe)物理位置的父目录开始。 如果未找到模块文件夹,则Python会上升一个级别,直到到达根目录为止。 为了理解这是一个包含模块的目录,Python查找os模块,该模块必须在os.py文件中,并且是python工作所需的模块。
假设我们的解释器位于
/usr/dev/lang/bin/python
。 然后,搜索路径将如下所示:
/usr/dev/lang/lib/python3.7/os.py /usr/dev/lib/python3.7/os.py /usr/lib/python3.7/os.py /lib/python3.7/os.py
如您所见,Python向我们的路径添加了一个特殊的前缀(
lib/python$VERSION/os.py
)。 解释器找到第一个匹配项(存在os.py文件)后,
sys.prefix
和
sys.exec_prefix
更改为此路径(已删除前缀)。 如果由于某种原因未找到匹配项,则使用标准路径,该路径将编译到解释器中。
现在,让我们看看最古老,最著名的库virtualenv是如何做到的。
user@arb:/usr/home/test
执行后,它将创建其他目录:
user@arb:/usr/home/test/ENV
如您所见,虚拟环境是通过将Python二进制文件复制到本地文件夹(ENV / bin / python)创建的。 我们还可以注意到,父文件夹包含指向python标准库文件的
符号链接 。 我们无法创建指向可执行文件的符号链接,因为 解释器仍会将其重命名为实际路径。
现在让我们激活环境:
user@arb:/usr/home/test
此命令更改$ PATH环境变量,以便
python
命令指向我们的本地python版本。 这是通过在$ PATH行的开头替换bin文件夹的本地路径来实现的,从而使本地路径优先于右侧的所有路径。
export "/usr/home/test/ENV/bin:$PATH" echo $PATH
如果在此环境中运行脚本,则将使用
/usr/home/test/ENV/bin/python
的二进制文件执行脚本。 解释器将使用此路径作为查找模块的起点。 在我们的例子中,标准库的模块位于
/usr/home/test/ENV/lib/python3.7/
路径中。
这是主要的技巧,所有用于虚拟环境的库都可以使用。
Python 3的改进
从Python 3.3版本开始,出现了一个新标准,称为
PEP 405 ,它引入了用于轻量级环境的新机制。
该PEP在搜索过程中增加了一个额外的步骤。 如果创建
pyenv.cfg
配置
pyenv.cfg
,则无需复制Python二进制文件及其所有模块,而只需在此配置中指示它们的位置即可。
标准
venv模块(在Python 3中出现)积极使用了此功能。
user@arb:/usr/home/test2
user@arb:/usr/home/test2
归功于此配置,venv无需复制二进制文件,只需创建指向它的链接即可。 如果将参数
include-system-site-packages
更改为
true
,则可以从虚拟环境中自动访问标准库的所有模块。
尽管有这些更改,但大多数用于虚拟环境的第三方库仍使用旧方法。
PS:我是本文的作者,您可以提出任何问题。