7个Python环境管理工具

通常,Python是一种非常灵活的编程语言--这一特性也体现到其环境管理中。不幸的是,这可能意味着您的Python安装变得混乱不堪。存在大量的环境管理工具来试图控制这种混乱……但是最终可能会变得更加复杂,尤其是对于新的Python开发人员而言!

在这篇文章中,我们将介绍可用工具的优缺点,以便您可以对如何安装python环境做出明智的决定。实际上,我们只需要在一些原则上达成共识:

  • 虚拟化是您的好帮手:避免每个项目之间的依赖冲突,实现项目之间互相隔离的Python环境可以使您的生活变得无比轻松

  • 项目应该是可复制的:依赖关系越紧密,您自己或其他开发人员实时复制代码的运行环境时就越容易

  • 自包含=可部署:所有的环境和依赖打包发布越容易,项目在不同的系统上运行(例如从开发环境迁移到部署)就越容易

所有Python虚拟化解决方案都可以满足这些要求-尽管像其他任何工具一样,您会发现关于哪种最好的强烈观点!我们的目标是使您能够就您的Python环境做出明智的决定,并为自己省去一些麻烦。我们将从最简单的低级标准工具开始,并逐步研究更新,更强大(尽管有时更深奥和更多限制)的选项,并一路讨论优缺点-我鼓励您考虑所有能够满足您项目的需求的选项 。

到底是谁的环境?

首先,新的Python程序员可能会想知道-当我们说环境控制时,我们在谈论什么?大致而言,我们希望了解三个控制级别:

  • 已安装的python包:我们可以将什么导入到正在运行的Python实例中?

  • 已安装的python二进制文件本身:我们实际上在运行什么版本和具有什么特色的Python?

  • 非python,系统级的依存关系:数字包底层的C / C ++工具链之类的东西怎么办?

如果能够显式地控制项目中的任何(或全部)事物,打包项目并使其在新的环境中启动和运行变得容易得多。最简单的说,Python中的大多数虚拟化工具都会创建一个虚拟环境,如下所示:

14510093-6d58ca2886fdad24.gif
image.gif

这样的目录包含运行Python实例需要的所有内容-bin中的二进制文件和可调用脚本(如特定环境的python可执行文件),lib中已安装的所有Python软件包以及所需的任何其他非Python头文件和配置。通过设置指向该目录的系统路径(通常使用激活脚本来完成),我们可以运行一个完全独立的Python版本,包括其可执行文件,已安装的软件包等。永远不要在此目录之外引用Python工具。除了项目独立的优势外,这也适用于需要在没有root权限的系统上运行Python的情况,因为我们可以在具有用户权限的位置中创建虚拟环境。

由于虚拟环境有自己的pip软件包管理器,因此将软件包安装到环境中很简单-我们只要在环境运行时简单地进行pip install即可,并且这些软件包会被放置在正确的位置。这也使我们可以指定环境的依赖-我们可以仅使用已知的Python版本(因为我们要使用相同的可执行文件)和列出了所需软件包及其版本的requirements.txt文件来重新创建环境,这些设置直接作用于pip install命令。

由于环境激活是由系统路径变量控制的,因此从技术上讲,我们可以将该目录放置在任何地方-不需要把环境包和项目放在一起,正如Node.js项目一样。保留虚拟环境及其关联的项目代码(假定它不被git记录,因为我们只需要实际追踪Python版本和requirements 文件,则可能会很有用),但是当您为所有的Python项目使用集中式目录时也同样适用。

因此,不用多说,让我们看看我们在环境管理方面有哪些选择!

内置:****venv

从3.3版开始,Python标准库附带了一个简单的内置工具venv,为了创建虚拟环境。只需调用

14510093-c6c03ef7ee3dd41d
image

(根据需要替换您的venv路径)将在指定目录中创建上述虚拟环境以及启动脚本-通过调用可以用来激活或停用该环境

14510093-70f1f8d0ef5b3940
image

激活后,pip install(独立软件包或来自requirements 文件)将按预期工作。要打包一个虚拟环境以在别处复制,您只需要生成一个包含环境内容的requirements 文件:

14510093-fe41254bc638352f
image

如果环境处于活动状态,则会生成一个requirements 文件,该文件可以安装到另一个系统上的全新虚拟环境中。

优点:

  • Python附带,无需其他工具

  • 创建一个几乎可以使用所有工具的标准虚拟环境:Requirements.txt适用于任何使用pip的环境管理器

缺点:

  • 只能管理安装的软件包:会适用任意Python来创建环境,因此您仍然无法人工管理Python版本

  • 除了pip安装可用以外别无选择

比venv更多:****virtualenv

实际上,有一个较旧的工具(可追溯到Python 2.x)可创建这些环境。实际上,venv是通过将virtualenv功能的子集引入Python 3.3+标准库中而创建的。仍然可以通过pip支持和安装该工具-尽管用户应注意,该工具仅适用于当前处于活动状态的Python(系统默认安装)。为了避免与系统软件包冲突(以及在用户缺乏安装到系统Python所需权限的情况下),可以使用pip install --user virtualenv在每个用户的基础上进行安装。安装后,调用类似于venv:

14510093-2f6e51e58e754cf0.gif
image.gif

在指定位置创建一个虚拟环境目录,可以像venv一样激活/停用该目录。值得注意的是,我们可以选择提供一个可调用的Python--venv为调用它的Python创建一个环境,virtualenv可以为系统上可用的任何Python安装创建一个环境,这意味着我们只通过从系统Python运行一个工具便能为其他Python创建环境(如果省略了-p选项,则默认为使用当前活动的Python版本)。创建后,pip install指令将依据名称或requirements 文件工作。

优点:

  • 创建与venv相同的标准虚拟环境,可与大多数工具完美配合

  • 可以通过相同的调用为任何已安装的Python创建环境

  • 包括一些高级功能,例如能够为环境创建引导脚本的功能

缺点:

  • 已安装的Python版本仍然需要手动管理

  • 需要管理系统Python的软件包安装

扩展到安装管理:****pyenv和pyenv-virtualenv

以上两种解决方案都只解决程序包管理-在这两种情况下,用户都只能手动管理已安装的Python版本。幸运的是,有一个出色的pyenv实用程序可以解决此问题,可以通过OSX上的自制程序或直接git checkout和build来安装。

设置完成后,可以轻松安装新的Python版本

14510093-3089de2ddce2a1c2.gif
image.gif

当前活动版本或所有安装的列表可以显示为

14510093-f13746fcba25a970.gif
image.gif

可以通过以下方式设置用户默认级别或指定某个项目的Python版本:

14510093-aa2b5a93e542b9b9.gif
image.gif

pyenv本身仅控制已安装的Python版本,而不控制虚拟环境。当然,在pyenv控制的Python版本中,我们可以轻松地使用venv或virtualenv来构建虚拟环境-但是pyenv开发人员还推出了pyenv-virtualenv插件,用于管理pyenv安装的Python版本的环境。通过homebrew 或git checkout + build安装后,运行

14510093-576cc189130ec6b8.gif
image.gif

会使用指定的pyenv管理的Python版本和给定名称创建虚拟环境(或者,可以省略Python版本以使用当前默认值)。虚拟环境可以通过以下方式激活或停用:

14510093-6b86f45546d14e2f.gif
image.gif

虚拟环境的安装位置由pyenv-virtualenv管理,因此我们不必担心为该环境指定目录(在我们的项目或中央位置)。但是,它是一个正常的虚拟环境,因此pip安装,需求文件等都可以像我们期望的那样工作。值得注意的是,pyenv会跟踪每个虚拟环境的Python版本,因此我们实际上可以使用pyenv local为项目目录设置特定的虚拟环境,而不仅仅是Python版本。

优点:

  • 没有Python依赖项,仅取决于shell命令

  • 一站式管理所有已安装的Python版本

  • 快速设置每个用户和每个项目的默认Python版本和虚拟环境,包括自动切换项目目录

  • 轻松创建与特定Python安装相关的virtualenvs

缺点:

  • 仅OSX / linux(尽管存在Windows端口)

  • 复杂的安装/设置过程

多合一:****pipenv

到目前为止,我们一直在使用多个工具来进行Python和环境管理,并将软件包安装到这些环境中-如果我们可以将所有这些都整合到一个工具中呢?Pipenv旨在通过将Python和强大的软件包版本控制(以Javascript的npm或yarn样式)捆绑在一起来做到这一点。通过软件包管理器(homebrew,apt,dnf等)安装或通过pip安装到现有的Python环境(建议与virtualenv一起作为用户级实用程序安装)之后,我们可以在项目目录中创建一个新的pipenv项目

14510093-33bef26a6780eb47
image

它将使用指定的Python版本初始化项目(如果安装了pyenv,它甚至可以按需安装Python版本)。首先,这将创建:

项目主目录中的一个Pipfile配置文件,指定Python版本,源和所有已安装的软件包,存放在pipenv工作目录中的全新虚拟环境

我们不再需要分别通过pip和虚拟环境来管理安装-Pipenv会同时照顾这两个!要安装软件包,只需运行

14510093-b0a4953868f0ad56.gif
image.gif

会将软件包安装到虚拟环境中,并将软件包作为依赖项写入Pipfile。那么,此Pipfile就是我们在其他地方重建项目所需的全部,而不是其他管理者使用的requirements.txt-仅在带有Pipfile的目录上运行pipenv install即可重新创建环境。要激活环境,

14510093-8208e90e6d212301.gif
image.gif

将使用该项目的虚拟环境启动新的Shell流程。

接下来,pipenv可以做一些相当独特的事情-它完全确定并指定项目的依赖关系。pip安装至少需要一个软件包名称来安装,例如点安装numpy的。我们当然可以指定版本限制,例如numpy == 1.18.1,在pip install命令或者requirements文件中。但是,除此之外,pip并没有进行太多验证-在拉取我们要安装的软件包的必需依赖项时,pip可能最终会拉取冲突版本,因此,除非我们实际检查了所有安装(例如手动安装所有依赖,然后直接从pip冻结生成requirements 文件),我们可能会遇到尝试从软件包requirements中重建环境的问题。相反,pipenv会详尽地构建依赖关系图,标记所有问题并生成经过验证的Pipfile.lock,以完全指定项目中的每个依赖关系。我们可以通过以下方式手动触发Pipfile中的要求

14510093-d3e000b562154f63.gif
image.gif

从Pipfile中拉出特别请求的程序包,并为Pipfile.lock生成依赖关系图。尽管这确实产生了可以确定性地重现的环境,但是依赖项解析可能非常复杂,因此,pipenv环境的编写要比只适用pip慢。

优点:

  • Python Packaging Authority正式支持

  • 用于项目,虚拟环境和包管理的单一工具

  • 与pyenv和conda配合使用可很好地处理Python和环境类型

  • 每个项目经过验证的确定性依赖

缺点:

  • 与其他管理工具不兼容,因此需要在项目和用户之间一致使用

  • 依赖解析很慢

**发展中的poetry **

同样,poetry 包括环境控制和依存关系解析,但poetry 更具体地针对Python软件包开发而不是常规项目控制。使用自定义安装程序安装后,我们可以使用

14510093-aa5ebdb521b1908c.gif
image.gif

它将通过一系列交互式提示来选择pyproject.toml配置文件,以指定项目的依赖项。如下:

14510093-e6b2d136cb460dee.gif
image.gif

将创建一个目录结构,如

14510093-923c4a7290e715f5.gif
image.gif

本质上,这已经创建了我们想要构建Python包的结构的框架,尽管配置TOML文件代替了标准库的打包工具所使用的setup.py文件。我们可以像这样添加项目依赖项

14510093-f4f3265ae6352836.gif
image.gif

之后正在运行的poetry install将所有指定的软件包安装到新的虚拟环境中(如果poetry已经在虚拟环境中运行,它将使用该软件包),同时确保poetry.lock文件中具有经过完全验证的依赖性。为了指定项目的Python版本,poetry可以与pyenv集成(或者您可以使用poetryenv使用<path>手动指定环境)。我们可以将该目录用于任何代码,但是在Python软件包构建中才是亮点-poetry构建和poetry发布将组合Python sdist和wheel软件包发行版,并将它们发布到您选择的存储库中。

优点:

  • 用于项目,虚拟环境和包管理的单一工具

  • 每个项目经过验证的确定性依赖

  • 集成的Python软件包构建/发布工具

缺点:

  • 依赖解析很慢

  • 需要特定工具的安装和更新,而不是使用库存包管理器

  • 工具更适合于打包项目,而不是应用程序开发之类的东西(但仍然可以用于它!)

  • 目前只能构建纯Python轮子,因此我们无法包含C / C ++依赖项或Cython集成代码

  • 不与其他环境/程序包管理器集成

挑战者出现:****anaconda

从历史上看,Python包管理一直面临一个主要问题-尽管Python包可能需要非Python依赖项(例如,Python中几乎所有数字工具都基于C / C ++),但无法控制这些包有意义地跟踪这些依赖项。较早的sdist(“源代码分发”)软件包分发版只能共享源代码,因此需要在主机上使用兼容的编译器来完全构建,软件包-编译器工具链之间的差异可能会在软件包安装中引入错误。尽管通过迁移到wheel发行版(包括共享对象.so文件等已编译的依赖项)极大地改善了这一点,但是Python的程序包树并未版本跟踪非Python的依赖项(因此,例如,他们实际上并不了解类似编译的依赖项中的版本更改)。

这个以及其他一些问题(例如在pip中缺少严格的依赖解析器)促使Anaconda的发展-一个多合一的Python发行版(尽管其行为与您习惯的普通Python可调用函数相同)和环境管理器称为conda,以及新的程序包分发格式。整个过程都随图形安装程序一起提供,该安装程序还将向启动脚本中注入指令,以便默认的Python来自Anaconda发行版。然后,我们可以使用以下内容使用conda管理器创建新的虚拟环境:

14510093-d1e93df6ecd792f5.gif
image.gif

并通过以下方式激活/停用环境

14510093-5d5acc5ffde1ea58.gif
image.gif

在conda环境中,只需运行

14510093-ddfc45a9f83f1fb3.gif
image.gif

将从conda库中提取软件包并将其安装到环境中。要导出conda环境或从导出的文件重新创建环境(相当于从requirements.txt文件进行安装):

14510093-33bb9eadce170a33.gif
image.gif

这是Anaconda / conda与我们在此讨论的其他管理器之间的最大区别-尽管其他一切都基于pip构建,并使用Python软件包的标准wheel 格式,conda从头开始重新设计环境中打包的方式,并采取了截然不同的哲学。简而言之:pip可在任何环境中安装python依赖项,而conda可在conda环境中安装任何依赖项。在conda环境中,您可以对依赖项进行细粒度的控制,其代价是只能在conda环境框架中发挥作用-程序包管理器与环境密不可分,并且依赖于包装结构和环境规范与其他Python工具不兼容。相比之下,pip在处理Python依赖项的环境方面是完全通用的(即使在更详细的环境管理器(例如pipenv和poetry)中也被广泛使用),并且可以安装到任何运行Python的环境中,包括conda环境。

所有这些意味着,Anaconda及其相关工具可以真正强大地启动并运行本地环境,并轻松管理自己的项目。因此,它是数据科学家的通用解决方案(并直接向其销售),这些科学家通常在自己的定制环境中运行代码,并且特别需要对数字包中已编译的依存关系进行干净处理。但是,与其他系统集成要困难得多(除非它们也都运行conda),尤其是在处理生产部署时。

优点:

  • 集成的Python分发,环境和包管理

  • 有意义地处理非Python依赖项

  • 包括严格的依赖解决方案,类似于pipenv和poetry

  • 附带有现成的数据科学堆栈

  • 跨平台工作

缺点:

  • 软件包管理未与标准软件包存储库集成,这意味着仍然有必要退回pip安装

  • 不与任何其他环境管理器集成,没有交叉兼容性

  • 与conda和pip安装的混合搭配可能很难复制

  • 全新的Python软件包开发工具链

如果它在您的计算机上可以运行,在所有计算机上都可以:docker

就本文而言,这有点奇怪,但它对环境管理至关重要,因此必须包括在内。与这里的其他工具不同,Docker根本不是Python环境管理器-而是容器管理器。每个Docker容器都运行一个轻量级的环境,其中包括位于隔离资源之上的所有代码,运行时,系统工具和库。从开发人员的角度来看,该容器似乎是运行Linux环境的完全独立的计算机,而没有整个虚拟机的资源开销-在同一台计算机上并行运行多个容器是完全可行的(例如,在构建一个虚拟机时)全栈应用程序,开发人员可能会同时为前端,后端和数据库实例运行单独的容器)。这使我们可以完全控制代码环境中的所有内容,甚至可以控制底层系统依赖性,还可以创建一个可移植的容器,该容器可以在运行Docker的任何地方精确地重现该环境。

确实,学习Docker本身就有必要,但我们快速通过一个示例来运行一些Python代码。首先,我们的项目目录如下所示:

在其中:

14510093-7c20992051d9886e
image

Dockerfile:用于构建Docker容器的说明。这些组合的指令构成了一个Docker映像,可以将其镜像用于任意数量的独立容器实例。

docker-compose.yml:运行容器的说明和设置。这是可选的,因为YAML中的所有操作都可以通过docker命令行调用来完成,但这使我们的生活变得更加轻松。

requirements.txt和Python代码:这就像您在其他任何环境中设置的Python一样。实际上,我们可以在其他任何管理器(例如, 我们可以轻松地运行pipenv并为容器包含一个Pipfile。

Dockerfile看起来像:

14510093-45a40afaac759c8d
image

其中我们:

  • 声明一个“基础映像”起点:在这种情况下,一个在Debian linux上运行的官方Python 3.7映像

  • 设置当前工作目录以用于后续说明

  • 将文件复制到容器中,以供后续命令使用

  • 执行安装命令:我们可以在RUN之后执行任何可以在容器操作系统的命令行中运行的指令

这将声明一个已安装所需Python版本的容器,然后引入并安装所需的程序包依赖关系-我们还可以使用RUN调用来安装任何必要的系统依赖项(C编译器,git调用以引入源代码等)。要构建和运行容器,我们可以使用docker命令行调用,但使用docker-compose包装器工具通常要简单得多。我们以YAML格式指定设置:

14510093-35888e5ac73a3835.gif
image.gif

这使我们可以为容器指定各种有用的信息:简写构建说明(因此docker-compose知道如何从Dockerfile构建映像),卷挂载以在容器和主机之间共享代码和数据(因此 我们可以实时编辑代码并重新运行它,而无需重建容器),用于系统控制的端口映射和环境变量,以及我们实际上希望它运行的命令。然后要构建我们的容器,我们只需要运行

14510093-2b1d3795abf703af
image

它将为compose 文件中指定的任何服务组合镜像。然后运行

14510093-2e86eac24f0f4f38
image

将在我们的命令行中启动一个Python Shell,在容器内运行(或者,对于后台服务,我们可以使用docker-compose up)。

最后,由于有很多选择,我们应该花点时间考虑使用哪个基本映像。从技术上讲,我们可以为我们选择的Linux发行版提取一个基础映像并在其上安装Python(例如,使用pyenv)-但是,如果我们对操作系统没有特定的需求,我们可以轻松地使用库存的python映像。这为我们提供了一个Debian环境,并在标记中列出了Python版本作为其系统Python(例如python:3.7.5将默认使用Python 3.7.5),并且没有冲突,因此我们可以像往常一样继续运行。或者,我们可以使用“苗条”的镜像(例如python:3.7.5-slim),这些镜像会去除一些可能不必要的系统依赖关系。我们可能需要重新添加这些内容-例如,某些具有已编译依赖性的程序包将需要gcc用于C编译器-但与“全脂”版本相比,它通常会产生明显更小的映像,并且可以很容易地重新建立依赖性--安装在Dockerfile指令中。

来自其他语言的开发人员可能会熟悉Alpine镜像类型-这是一个为安全性和尺寸限制而设计的精简发行版。确实存在Alpine python镜像,但我强烈警告不要使用它们。Alpine对其所有C依赖项都使用musl工具链(再次出于大小和安全性考虑),而出于性能方面的考虑,Python软件包通常在假设glibc工具链的情况下构建了其依赖项。要使这些软件包在Alpine上运行,要么需要重建glibc工具链,要么为musl重建这些软件包-无论哪种方式,这对于开发人员来说都是头疼的问题,并且会产生与苗条版本相当的图像,从而消除了在Alpine中使用Alpine的优势。第一名。除非您对Alpine有特定的部署需求,否则建议您默认使用苗条的Python。另外,如果您已经熟悉并喜欢使用Anaconda工具,则可以使用受支持的anaconda和miniconda(精简,较小的发行版)Docker基础映像。

优点:

  • 完全控制我们所有的依赖关系,直至系统级别-甚至可以使用本文中的任何环境管理器

  • 明确指定所有指令以复制代码环境

  • 容器可以很容易地打包和运输以在生产环境中运行

  • 通用指令可以内置到新的基础映像中,并在项目之间重复使用

  • 可以以编程方式定义在单个docker-compose规范中独立运行的多个服务之间的交互

缺点:

  • 全新的API学习

  • 在Alpine镜像上构建工具的怪异变化莫测

总结

当然,我说这些工具都可以用于环境管理-是的,但这并不意味着我没有自己的见解!在所有这些中,我更喜欢在本地计算机上使用pyenv / pyenv-virtualenv进行控制,尽管对于大多数项目,我将继续使用Docker(如果不希望以root身份运行,则可以使用venv)对我的代码具有最大程度的控制和最简单的部署。在几乎所有情况下,我都会默认使用slim Python镜像,因为这在镜像大小与消除不必要的依赖关系以及确保可以轻松获得所需工具之间取得了良好的平衡。

我通常发现依赖关系解决不再是一个问题(尤其是对于高度隔离的项目),因此发现诸如pipenv或poetry之类的工具就没有那么必要了-尽管对于大型项目来说这是一个好主意,而更好的依赖关系解决方法是将这个问题作为Python软件组织的高优先级。对于具有重大依赖性问题的项目,在Docker容器上运行pipenv是一个很好的解决方案。

处理生产环境的困难比起处理Python软件包wheel 格式(自Anaconda的开发以来引入)提供的编译依赖项的处理带来的收益,意味着我宁愿完全避免使用conda作为环境管理器。虽然它面向数据科学家销售,但我发现,看起来更像生产的代码设置,再加上Docker提供的一致的构建环境,从长远来看是有回报的。

英文原文:https://www.pluralsight.com/tech-blog/managing-python-environments/
译者:QL
电子书
我总结的82页《Python之路V1.1.pdf》,都是干货520 页机器学习笔记!图文并茂可能更适合你,文末附下载方法
541页的《利用Python进行数据分析》(附电子书和源码下载)386页《Python深度学习》电子书及源码下载
基于TensorFlow 2.0的中文深度学习开源书来了!GitHub趋势日榜第一,斩获2K+星
【资源】吴恩达新书《Machine Learning Yearning》,附中文版PDF下载
343页经典书籍《算法之道(第二版)》pdf下载
下载 | Python 学习手册(第 4 版)
下载 | 《Python数据科学速查表中文版》

这里除了干货一无所有

14510093-b3f494e1c01053af
image

看完本文有收获?

</pre>

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值