您真的不需要virtualenv

2021-02-06 19:58:40

开发Python项目时,需要安装项目的依赖项。长期以来,教程和文章都告诉您使用虚拟环境来隔离项目的依赖关系。这样,您就不会污染其他项目的工作集或全局解释器,以避免可能的版本冲突。我们通常必须执行以下操作:

$ python3 -m venv venv#创建一个名为`venv`的virtualenv $ venv / bin / activate#激活virtualenv(venv)$ pip install -r requirements.txt#安装依赖项

也有简化此过程的工作流工具,例如Pipenv和Poetry。他们为您创建了虚拟环境,而无需感知,然后将依赖项安装到其中。它们被广泛的用户使用。虚拟环境包含一个Python解释器,并且具有与普通安装相同的目录结构,因此可以像使用独立的Python安装一样使用它。

Virtualenvs可以帮助我们隔离项目依赖关系,但是在嵌套venvs方面会变得棘手:使用venv封装的Python安装virtualenv管理器(例如Pipenv或Poetry),然后使用基于封装的Python的工具创建更多的venvs。有一天,一个较小的Python版本发布了,必须检查所有这些venv并根据需要对其进行升级,然后才能安全删除过时的Python版本。

另一种情况是全局工具。有许多工具没有与任何特定的virtualenv绑定,而是应该与每个工具一起使用。示例包括分析工具和第三方REPL。我们也希望将它们安装在自己的隔离环境中。即使您已激活要处理的目标项目的virtualenv,也无法使其与virtualenv一起使用,因为该工具位于其自己的virtualenv中,并且只能看到其中安装的库。因此,我们必须为每个项目安装该工具。

在过去的两年中,我一直以协作者的身份维持Pipenv项目,并在2020年初成为PyPA的成员。我一直在思考虚拟环境是否真的是Python项目必不可少的,就像npm,它不需要克隆的节点二进制文件,而只需要每个项目唯一的node_modules目录。

该解决方案已经存在很长时间了。 PEP 582起源于2018年,直到我撰写本文时仍是一项提案草案,但我发现它正是Python中的node_modules。

.├──__pypackages__│└──3.8│└──lib└──my_script.py

如PEP 582中所指定,如果您运行python3.8 /path/to/my_script.py,则__pypackages __ / 3.8 / lib将被添加到sys.path,并且内部库将可在my_script.py中导入。

现在,让我们回顾一下我在上一节中提到的两个问题,并看看它们是如何随着PEP 582的功能而变化的。对于第一个问题,主要原因是虚拟环境绑定到了一个克隆的Python解释器上,后续基于库的搜索。它利用了Python现有的机制,没有进行任何其他复杂的更改,但是当Python解释器过时时,整个虚拟环境将变得不可用。使用本地软件包目录,您将不再拥有Python解释器,库路径直接附加到sys.path,因此您可以自由移动和复制它。

再次,您只需要针对要分析的项目调用该工具,位于项目内部的__pypackages__将自动加载。这样,您只需要保留一份全局工具的副本,并使其可用于多个项目。

从PEP开始,我制作了PDM,这是一个新的Python包管理器和工作流工具,它利用PEP 582完全摆脱了virtualenv。它将依赖项安装到本地包目录__package__中,并使Python解释器可以通过非常简单的设置来了解它。它不仅是PEP 582的实现,而且是唯一支持PEP 621的程序包管理器,PEP 621是基于pyproject.toml的新元数据格式,最近成为标准。可以预见,pip也将逐渐支持此格式。此外,PDM使用与pip相同的依赖项解析器,并具有功能齐全的插件系统,从而允许社区贡献的插件来增强功能。

在PDM中,PEP 582不是必需的,您也可以坚持使用virtualenv。 PDM可以检测现有的静脉,但不能创建新的静脉。

值得注意的另一件事是其依赖关系解析机制-它试图锁定与项目的require-python值兼容的版本。假设您的项目需要使用Python 2.7或3.6更高版本,并且要添加pytest作为开发依赖项,在Pipenv(ver。2020.11.15)中,您必须固定pytest ="< 5"手动在Pipfile中。在诗歌(1.1.4版)中,如果您运行诗歌,请添加-D pytest,您将获得:

当前项目的Python要求(> = 2.7,< 3.0 ||> = 3.6,< 4.0)与某些必需的Python软件包不兼容:-pytest需要Python> = 3.6,因此对于Python> = 2.7,< 3.0

是的,它告诉您升级您的Python需要版本。但是,在PDM中,您可以成功锁定:

❯pdm add -d pytest将软件包添加到dev依赖项中:pytest✔🔒锁定成功将更改写入pdm.lock。将更改写入pyproject.toml。与锁定文件同步工作:添加11个,更新0个,删除0个✔安装atomicwrites 1.4.0成功✔安装colorama 0.4.4成功✔安装包装20.8成功✔安装more-itertools 5.0.0成功✔安装pyparsing 2.4.7成功✔安装attrs 20.3.0成功✔安装pluggy 0.13.1成功✔安装py 1.10.0成功✔安装pytest 4.6.11成功✔安装六个1.15.0成功✔安装wcwidth 0.2.5成功🎉全部完成!

如您所见,pytest固定到与Python 2.7和Python 3.6+兼容的4. *。

您可能以前看过这部漫画,在Python世界中已经有这么多的软件包管理器,我们需要一个新的软件包管理器吗?不,我想。很高兴我们看到Python封装生态系统和官方安装程序pip有了很多改进,例如PEP 517 / PEP 518和新的依赖项解析器,这些在将来还会有更多改进。但是,在一天到来之前,为什么不尝试尝试不同于传统的尝试,为什么不尝试使自己至少感到高兴的新事物呢?如果您这样认为,希望可以选择PDM。