如果你是一个Python开发人员,你可能听说过Virtual Environments。Virtual Environments是“一个自包含的目录树,其中包含特定版本的Python安装环境,以及一些额外的包”。
它们为什么这么受欢迎?因为,它们解决了一个问题:不需要再将所有包都安装到全局site-packages组成的大杂烩中。相反,每个项目可以在它们自己的“虚拟”环境中安装精确的依赖项版本。
然而,它们也带来了一些问题:
学习曲线:向那些只想进入虚拟环境并编写代码的人解释“虚拟环境”并不总是那么容易
终端隔离:Virtual Environments的激活和停用基于每个终端
认知开销:设置、记住安装位置、激活/停用
为了解决上述问题,我们创造了新的高级工具,如pipenv、poetry、flit和hatch。这些工具通过隐藏pip和Virtual Environments的复杂性来改善这种情况。然而,为了隐藏复杂性,它们本身又变得比较复杂。它们也有自己的API、学习曲线和维护负担。
走进PEP 582 ——Python本地包目录
早在2018年5月,就引入了一个Python增强提案(PEP)来修改Python本身以解决由虚拟环境解决的许多问题,但采用了一种完全不同且比较简单的方法。请注意,该PEP仍然处于草案状态,因此它可能仍然会更改,或者甚至可能根本不会被采纳。
我们来看一下PEP 582[1]中的一段话:
本PEP提案向Python中添加一种机制来自动识别__pypackages__目录,并且优先导入安装在该位置的包,而不是用户或全局site-packages。这将避免创建、激活或停用“虚拟环境”的步骤。Python将使用脚本所在根目录中的__pypackages__,如果这个目录存在的话。
本提案通过搜索本地路径来寻找额外的包,从而有效地解决了Virtual Environments及其高级副本的所有复杂性。
现在就尝试一下
它甚至附带了一个参考CPython实现[2]。
如果你没有时间或者没有兴趣构建一个CPython二进制文件,那么可以尝试我创建的Python包装器的概念验证,称为pythonloc[3](指代“Python local”)。这是一个Python包(少于100行代码),它完成了PEP 582所描述的工作。
pythonloc运行Python,但会从__pypackages__中导入包(如果存在的话)。它还附带piploc,piploc与pip相同,只不过piploc是安装/卸载到__pypackages__。
这里有一个例子。
注意:这可能与你在site packages目录中找到的内容相同,比如~/.local/lib/python3.6/site-packages。
如你所见,piploc将requests包安装到了__pypackages__/3.6/lib/requests。运行python表明它没有找到requests包(这是意料之中的,因为它没有搜索__pypackages__目录)。
要让Python找到它,你可以运行pythonloc,这与运行PYTHONPATH=.:__pypackages__:$PYTHONPATH python是相同的。这样程序运行是就会搜索__pypackages__目录并找到requests安装。
现在,你可以通过运行以下代码来尝试pythonloc:
你可以访问https://github.com/cs01/pythonloc来学习更多。
安装多个依赖项或锁文件
如果你有可用的源代码,并且它有一个setup.py文件,你可以运行
然后运行pythonloc并使所有依赖项可用。
如果你有一个requirements.txt文件,你可以运行
如果你正在使用pipenv,那么你可以通过以下代码生成一个requirements.txt文件
最后,如果你正在使用poetry,那么你可以使用以下代码生成requirements.txt文件
冻结依赖性
虽然我们可以从各种源来安装依赖项,但如果我们正在开发并想要生成一个依赖项列表呢。
随着__pypackages__的出现,你可以使用一种新的工作流来创建依赖项列表,并将__pypackages__本身提交到源代码控制中。这样做实际上可以保证你使用的是相同的版本,因为你使用的是完全相同的源代码。
假设你不想这样做,那么可以运行piploc freeze。但这带来了一个问题。它显示了所有已安装的python包:site-packages中的包以及__pypackages__中的包。这可能不是你想要的,因为它包含的内容比你安装到__pypackages__的内容要多。
你可能只想输出安装到__pypackages__中的包。这正是pipfreezeloc所做的。
它相当于pip freeze,但只输出__pypackages__中的包。这是必需的,因为在pip中没有内置的方法来实现这一点。例如,命令pip freeze --target __pypackages__并不存在。
因此代替运行
你可以运行
结 论
PEP 582是一个提案草案,它引入了一种新的方法来在没有Virtual Environments的情况下安装和隔离包。它还消除了项目位置和环境位置之间的间接关系,因为安装位置始终与项目位置在相同的目录中——在__pypackages__中。
pythonloc(和piploc,pipfreezeloc)是目前可用的PEP 582 Python实现的一个概念验证。
你怎么认为?PEP 582是否应该被批准(请注意,在此过程中我不是决策者,只是一个感兴趣的观察者)? Virtual Environments的依赖性会降低吗?pythonloc改善了你的工作流程吗?
相关连接:
[1]——https://www.python.org/dev/peps/pep-0582/
[2]——https://github.com/kushaldas/cpython/tree/pypackages
[3]——https://github.com/cs01/pythonloc
英文原文:https://qiniumedia.freelycode.com/vcdn/1/%E4%BC%98%E8%B4%A8%E6%96%87%E7%AB%A0%E9%95%BF%E5%9B%BE3/goodbyevirtualenvironments.pdf
译者:一瞬
领取专属 10元无门槛券
私享最新 技术干货