首页 > 编程知识 正文

anaconda pipenv(pipe)

时间:2023-05-04 17:20:57 阅读:85096 作者:4626

前言

俗话说,工作要做好自己,就一定要先利其器。 我们写代码也是如此。 在Python开发中,如何管理Python运行环境、package依赖关系是任何开发者都无法回避的问题。 在PyCon2018上,热情之石Reitz介绍的Pipenv是解决这类问题的大杀器。

为什么需要Pipenv?

要理解hxdym Reitz为什么开发Pipenv,必须从Python的软件包管理工具的发展历史开始。

python打包的历史

Distutils

早期的Python提供了一个名为distutils的内置模块。 使用此模块,开发人员可以创建自己的package的setup.py文件,并将其全部打包上载到internet。 如果用户想要安装此包,则首先从网上下载文件(通常是tar包等),解压缩后运行Python setup.py install,然后运行python的site-packages

PyPI

PyPI的全名是python package索引,可以理解为集中索引,开发人员可以在此上传package及其元数据。 如果有PyPI,其他开发人员可以从上面下载所需的软件包,然后运行python setup.py install进行安装。 尽管如此,还是有一些问题:

整个过程需要人手,不便于自动化的package都是全球安装的,不能同时安装同一package的两个不同版本,很麻烦,用户体验很差的Setuptools

Setuptools的出现弥补了distutils中存在的一些缺点,提供了更丰富的功能。 可以认为Setuptools是对distutils的一系列扩展,如egg安装文件的支持、自动安装工具(easy_install )、distutils的monkey-patch等。 如果有easy_install,当用户想要安装某个package时,只需要执行easy_install package,工具就会自动将package及其依赖关系(默认情况下从官方的PyPI开始)导出到文件夹中与以前的软件包安装方法相比,easy_install具有以下优点:

更好的用户安装体验大多数package来自PyPI,适合自动化。 关于缺点,最重要的是没有easy_uninstall。 也就是说,只能使用easy_install安装软件包,但没有适当的工具来卸载。

pip

到2008年,pip作为easy_install的替代者出现。 虽然pip的大部分构建在setuptools的各个部件之上,但是与easy_install相比提供了更强大的功能。 特别是引入了Requirements Files的概念,使用户可以轻松复制Python环境。 如果在一个环境中运行pip freeze requirements.txt,导出当前环境中的所有包信息,然后在新环境中运行pip安装- r请求. txt,则pip将返回这些包如果不需要软件包,也可以运行pip卸载软件包进行卸载。 迄今为止,pip已经成为最受Python开发者欢迎的软件包管理工具。

虚拟现实

pip解决了单个环境中的大部分package管理问题,但通常在一台机器上同时开发多个项目。 项目a需要Python2.7和Flask0.9,项目b需要Python3.6和Flask1.0,项目c需要Python3.6和Flask1.0.2。 这样,我们面临着两个问题。

对于项目a和b,或者项目a和c,如何区分它们使用的不同版本的Python和快速开关? 对于项目b和c,由于使用的是Python3.6,因此安装的第三方软件包位于Python3.6的site-packages目录下。 那么,如何区分所需的不同版本的Flask呢? 对于第一个问题,可以安装所有必要的Python,分别指定不同的alias,在开发不同的项目时使用不同的alias。 虽然此方法有效,但很复杂,容易出错,如果开发人员忘记使用alias或使用了错误的alias,则可能会在错误版本的Python下安装软件包。

关于第二个问题,光靠pip很难解决。 因为同一版本的Python的所有第三方包都在site-packages下,无法区分不同的版本。

要解决上述问题,需要一个名为virtualenv的新工具。 virtualenv可以为每个项目创建隔离的Python环境,以防止系统中不同的Python环境之间相互影响。 在每个隔离的环境下,使用pip进行软件包管理。 pip virtualenv是目前主流的Python开发过程。

更进一步

如上所述,pip virtualenv的工作方式成为主流,至今仍在继续。 但是,这种方法也有一些不足。

新人(特别是不知道Unix相关概念的新人)很难分辨virtualenv的抽象层是什么样的vi

rtualenv的工作流程比较繁琐,对人来说不够自然,尽管virtualenv-wrapper的出现一定程度上缓解了这个问题pip的requirements.txt过于简单,没法表示具体的依赖关系需要使用两个工具(pip+virtualenv)才能完成工作,不够便捷

下面是在只安装了Flask的环境中执行pip freeze导出的requirements.txt。可以看到,里面包含了Flask本身及其依赖,每个package的版本都是确定的,但是没法看出它们之间的具体依赖关系是怎样的。试想,如果我们想使用一个开源项目,看到这样一个requirements.txt,我们可能会误以为这个项目直接依赖了这些packages,但实际上它只是直接依赖了Flask。

另一种requirements.txt的写法就是,我们只给定需要直接依赖的package名称,像下面这样。使用这种方式,我们一眼就能看出项目直接依赖了哪些package。但是这里有个问题,即Flask及其依赖的版本是不确定的。如果过段时间某个依赖发布了新版本,你去新环境部署的时候pip就会给你装上新的版本,可能会导致你的代码没法工作。

以上就是激情的石头的演讲中举的例子,用来说明"what you want"和"what you need"之间的不匹配。

Pipfile & Pipfile.lock

为了解决"what you want"和"what you need"之间的不匹配问题,Pipfile这个新的标准被提了出来。

Pipfile被设计用来取代requirements.txt。其优点主要在于:

采用TOML语法,相比requirements.txt表达能力更强默认支持两组依赖:[packages]和[dev-packages],可以将多个requirements.txt的内容合并到一个文件,方便管理可以通过Pipfile.lock对环境进行明确、详细地描述

Pipfile大致是这么个样子:

通过对Pipfile进行处理,可以生成JSON格式的Pipfile.lock,包含了所有依赖及其具体的版本号,还有每个release的hash。比如下面:

大家可以理解成,Pipfile只描述了你想要的package是哪些,是抽象而宽泛的,比如上面Pipfile的例子描述了我们需要Flask这个package。而Pipfile.lock则是对你在实际运行环境里需要的package以及它们所有依赖的描述,是具体而明确的,比如上面Pipfile.lock的例子描述了Flask以及其依赖的具体信息,这样当我们想在新环境里运行我们的项目时,就可以按照这些信息来安装所有依赖的package,确保环境的一致性。实际上,很多语言的package管理工具都支持类似Pipfile.lock这样的Lockfile,比如Node.js的yarn和npm,PHP的Composer,Rust的Cargo以及Ruby的Bundler。

Pipenv

激情的石头 Reitz开发的Pipenv,将Pipfile,pip和virtualenv整合到了一起,让我们只使用这一个工具就可以非常方便、流畅地管理自己的Python环境。Pipenv的主要优点:

可以让你无缝使用Pipfile和Pipfile.lock,保证每个依赖的信息都是明确的提供简洁的命令帮你操作virtualenv提供其他辅助工具,比如pipenv graph,可以显示项目完整的依赖关系

现在Pipenv已经是Python官方推荐的工作流(package管理+virtual env管理)工具了。

Pipenv用法简介

首先安装pipenv:

然后我们创建一个workspace并切换到该目录下(我这里是~/workspaces/pipenv_demo),创建一个新的环境:

如果要指定Python版本,可以使用--python参数:

创建完后,目录下就会生成Pipfile和Pipfile.lock两个文件:

下一步,我们安装Requests:

安装完毕之后,我们Pipfile就会变成下面这个样子:

而Pipfile.lock则是这样:

运行pipenv graph可以将环境中的完整依赖打印出来:

这个时候,如果我们直接运行Python交互模式,尝试import requests会报错,因为还没有激活virtual env:

Pipenv提供了一个非常好用的命令:pipenv shell,用于激活virtual env:

可以看到,当激活virtual env后,命令行提示符前面多了'(pipenv_demo-B6h7SXri)',这个就相当于我们virtual env的id,表示我们现在处于这个virtual env下。再次尝试在交互模式中import requests,成功:

当不需要virtual env时,只需要运行exit即可:

通常我们需要把Pipfile和Pipfile.lock也加到版本管理中,以能保证同一个项目的不同开发者的Python环境保持一致。比如我们新加入了一个项目,就可以把repo clone下来,直接运行pipenv install,pipenv会自动找到已存在的Pipfile和Pipfile.lock,并根据里面的信息来安装依赖,这样我们就能准确无误地复制其他人的环境了。

总结

就像激情的石头 Reitz演讲标题所写的那样,Pipenv是Python依赖管理的未来。作为一名合格的Python开发者,还是有必要学习下这个工具,提升自己的工作效率,也享受更好的工作体验。

参考

Pipenv - The Future of Python Dependency Management

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。