什么是 pip ?pip 是 Python 中的标准库管理器。它允许你安装和管理不属于 Python标准库 的其它软件包。本教程就是为 Python 新手介绍 pip。
通过本教程,你将学到:
1. 安装 Python 的标准发行版中未包含的其他软件包
2. 查找发布于 Python 包索引(PyPI)的包
3. 管理脚本和应用程序的安装需求
4. 卸载包及它的相关依赖
如你所见,Python 社区非常活跃,并且为 pip 创建了一些简洁的替代方案,你可以在本教程稍后的部分看到。
pip 入门
那么,什么是 pip 呢?pip 是 Python 的包管理器。这意味着它是一个工具,允许你安装和管理不属于标准库的其他库和依赖。
软件包管理极其重要,所以自 Python3 的 3.4 版本以及 Python2 的 2.7.9 版本开始,pip 一直被直接包括在 Python 的安装包内,同样还被用于 Python 的其它项目中,这使得 pip 成为了每一个 Pythonista(Python用户)必备的工具。
如果你已经了解了其他语言,那么可能会对包管理器的概念比较熟悉。JavaScript 使用 npm 管理软件包,Ruby 使用 gem,以及 .NET 使用 NuGet。Python 中,则是 pip 作为标准包管理器。
Python 的安装器中自带了 pip,所以你可以直接使用它,除非你安装的是更早版本的 Python。你可以通过在控制台中运行以下命令来验证 pip 是否可用:
你应该可以看到一个类似的输出,显示 pip 的版本以及安装位置还有 Python 的版本。如果你使用的是不包含 pip 的旧版本 Python,你可以根据 pip 安装文档中相应系统的说明进行安装。
你可能希望在虚拟环境中使用本教程的示例,以避免将包安装到 Python 的全局安装环境中。你可以从 Python 虚拟环境:入门级了解虚拟环境相关的信息,这篇文章的”使用虚拟环境“一节介绍了创建虚拟环境的基础知识。
使用 pip 安装软件包
Python 被认为是一种"内置电池"式的语言。这表示 Python 标准库包含大量的软件包和模块,这些模块有助于开发人员开发脚本和应用。
与此同时,Python 拥有一个活跃的社区,它提供了一个更大的软件包集合,以供你开发所需。这些软件包发布在 Python Package Index,也被称为 PyPI(发音 Pie Pea Eye)。PyPI 托管了大量包,包括开发框架,工具和库。
其中很多软件包通过为已有功能提供了友好地接口来简化 Python 开发。例如,你可以写一个脚本,仅使用 Python 标准库中的功能分析网页的内容:
脚本中,导入了 cgi 和 http.client,这两个都是在 Python 的标准库中。你创建了一个 HTTPSConnection 对象并指定服务器,然后调用 .request() 和 .getresponse() 解析响应信息。
从响应信息中,我们解析到 Content-Type 头信息并且使用 cgi 模块提取页面编码的字符集。
cgi.parse_header() 返回一个包括主要值和字典作为参数的元组。例如,Content-Type 头信息可能包含一个像 text/html; charset=ISO-8859-1 的值。
这个元组将字符串 text/html 作为第一个元素,第二个元素是 {'charset': 'ISO-8859-1'} 这样形式的字典。因为你只需要关心 charset 参数,可以使用下划线忽略元组的开头:_, params = cgi.parse_header(content_type)。
注意:Python 中下划线的含义解释了如何从元组解包值。
对页面编码后,你可以阅读相应信息并解码到文本中。你可以在控制台中运行这个例子查看它是怎么工作的:
对于一个用于解析网页内容的小脚本来说,这看起来做的工作有点多。幸运的是,有一个 Python 的包可以简化 HTTP 请求并提供了一个友好地接口来实现你的期望。
基础包安装
PyPI 托管了一个非常流行的库 requests 来完成 HTTP 请求。你可以通过它的官方文档站点了解所有的相关信息。
第一步是在你的环境中安装 requests 包。你可以运行 pip help 来了解 pip 支持的命令:
如你所见,pip 提供了 install 命令来安装软件包。你可以运行它来安装 requests 包:
你可以看到与上面类似的输出信息。你可以使用 pip 以及 install 命令,其后跟着你想要安装的包名。pip 会在 PyPI 中查找这个包,计算其依赖关系,安装并确保 requests 正常工作。
你还可以看到当前环境下 pip 的版本是 18.1,但是还有 19.0.1 版本可用。它还显示了用于升级 pip 的命令,所以我们来试一下:
注意这里,你使用了 python -m 来升级 pip。-m 开关告诉 Python 将模块作为可执行文件运行。如果你要升级 pip,这么做是很有必要的,在安装新的版本之前会卸载旧的版本,而当工具在运行时卸载它自己会导致错误。
当你将 pip 作为一个模块运行时,Python 会将模块加载到内存中,并允许在这个模块包运行的时候删除它。如果软件包提供了顶层脚本 main.py,那么你可以像运行脚本一下运行这个软件包。
你已经安装了 requests 并升级了 pip,现在可以使用 list 命令查看你的环境中安装了哪些软件包。
如上所示,pip 已经升级到了 19.0.1 版本(目前最新版本),并且安装了 requests 2.21.0 版本。
命令 pip install 会查找并安装软件包的最新版本。同时还会搜索软件包元数据中的依赖列表,并安装这些依赖以确保软件包满足所有的需求。
这里你可以看到安装了很多软件。你可以使用 pip 中的 show 命令查看包的元数据信息:
[图片上传失败...(image-90ab4f-1565242498214)]
元数据中列出了依赖项 certifi,chardet,idna 和 urllib3,而且你可以看到这些都已经安装好了。
既然已经安装了 requests 包,我们可以修改上面的例子,来看看如何更方便地解析网页的内容:
因为你已经在开发环境中安装了 requests 包,可以像导入其他标准库一样导入它。
可以看到,requests.get() 处理了 HTTP 连接并返回一个与之前例子相似的响应,但是简洁方便了很多。
因为 requests 已经帮你处理了大部分情况,所以你不需要考虑页面的编码问题。而且,requests 还通过 requests.Response 对象提供了一个更加灵活的接口来处理特殊情况。
使用 requirements.txt 需求文件
pip install 命令只会安装最新发布的软件包版本,但是有时候,你可能希望根据代码运行情况安装特定的版本。
你还希望在开发和测试时指定创建的依赖和版本,这样就可以在生产环境避免应用程序出现意外情况。
需求文件可以精确指定需要安装的软件包和版本。运行 pip help 你可以看到一个 freeze 命令,它会按照格式化输出以已经安装的软件包。你可以使用这个命令,将输出重定向到文件以生成一个需求文件:
freeze 命令将所有软件包以及版本信息转储到标准输出,所以你可以重定向这些输出到文件中。这样就可以在其他系统中根据这个需求文件执行精准安装。约定这个需求文件名为 requirements.txt,但是你也可以根据个人喜好命名。
如果你希望在其他系统中复制你的开发环境,你可以运行 pip install 命令并用 -r 开关指定需求文件:
软件包的版本会根据 requirements.txt 所列出的进行匹配:
你可以将 requirements.txt 文件提交到资源控制器,这样就可以使用它在其它机器上创建精准匹配的环境了。
微调需求文件
软件包及其依赖的版本可能会导致硬编码问题,这是因为软件包会针对 bug 以及安全修复进行频繁的更新,而你可能希望在它们发布后立即做出更改。
需求文件的格式允许你使用逻辑运算符指定依赖的版本,这为确保更新包提供了更多的灵活性,但是仍然要定义一个包的基础版本。
使用你常用的编辑器并作以下修改:
你可以通过改变逻辑运算符为 >= 来告知 pip 精准安装已发布的指定版本或更高版本。当你使用 requirments.txt 设置了一个新的环境,pip 会查找满足需求的最新版本并安装。你可以使用带有 --upgrade 开关的 install 命令来升级你需求文件中定义的软件包:
这里没有任何升级操作,因为你的软件都是最新版本,但是如果在包列表中发布了新的版本,那么这个包就会被升级到最新版本。
理想情况下,新版本的包会向后兼容并且没有新引入的 bug。不幸的是,新版本引入的更改还是可能会破坏你的应用程序。需求文件的语法支持额外的版本说明符来微调你的需求。
比方说 requests 发布了新版本 3.0,但是有一些更改与你的应用程序不兼容。你可以通过修改需求文件来禁止安装 3.0 版本以及更高的版本:
更改 requests 的版本操作符可以确保不会安装 3.0 或更高的版本。pip 的文档提供了全部的需求文件格式,你可以查阅以了解更多相关信息。
生产与开发环境的依赖关系
你在开发期间安装的依赖并不都是你的应用程序的依赖。其中有很多发布到 PyPI 上的包,是你开发过程中想用到的工具或库。
比方说,你可能希望对你的应用做单元测试,你需要单元测试的框架。一个流行的单元测试框架是 pytest。你希望在你的开发环境中安装它,但是却不希望在生产环境也安装它,因为它不是应用的依赖。
这时你会创建第二个需求文件(requirements_dev.txt)来列出配置开发环境需要的工具:
这里需要你使用 pip 安装两个需求文件:requirements.txt 和 requirements_dev.txt。还好,pip 允许在需求文件内部指定一些额外的参数。你可以需改 requirements_dev.txt 文件支持同时安装生产文件 requirements.txt 中的需求:
注意这里你使用了完全相同的 -r 开关来安装生产文件 requirements.txt。需求文件格式允许你在需求文件中指定其他参数。
为生产环境冻结需求文件
你已经创建了生产和开发环境的需求文件,并将它们添加到资源控制器中。这些文件可以灵活 的指定版本,可以通过发布的依赖进行修复 bug。你还可以测试你的应用程序并为发布到生产环境做准备。
因为已经知道开发环境应用程序的所有测试已经正常通过,所以你可能希望确保生产环境的依赖版本与整合管道或构建过程中使用的完全相同。
目前的版本说明符并不能保证会在生产环境部署完全相同的版本,所以你需要冻结说明文件 ,像之前看到的那样。
你创建了一个干净的生产环境,并使用 requirements.txt 文件安装了生产需求。安装完需求文件之后,你可以冻结当前这个特定的版本,并将输出转储到生产环境的 requirements_lock.txt 文件中。该 requirements_lock.txt 文件中包含精确的版本说明符,并且可以复制当前环境。
搜索可用包
当你拥有更多的 Python 经验之后,会有一套熟悉的软件包,并且可以用于大部分应用程序。包 requesta 与 pytest 对于补充你的 Python 工具箱来说,都是很好的选择。
有时你需要解决不同的问题,并想要找到一个可以帮助你解决问题的工具或库。上面提到,命令 pip help 展示了一个命令 search,可以搜索在 PyPI 上发布包。
我们看看这个命令有什么用:
这个命令给出了一组选项以及一个 参数。query 是一个用于搜索的字符串,可以匹配包名及描述。
注意:你可以使用 pip help 检索其它支持的命令的信息。
假设你的应用需要访问一个使用 OAuth2 授权的服务。理想情况下,会有一个库使用 requests 执行或者其它类似的接口实现。用 pip 到 PyPI 上搜索一下:
search 命令选项生成了一个相当大的包集合。其中一些看起来像 django-oauth 这样指定了一个服务或技术。希望找到一个像是 requests-oauth 的信息。很不幸,除了简短的描述,并没有其它信息。
多数情况下,你希望直接在 PyPI 的网站搜索包。PyPI 为其索引提供了搜索功能,并通过包中公开的元数据(如框架,主题,开发状态等)过滤搜索结果。
PyPI 中用同一个术语搜索可能会产生大量的结果,不过你可以对它们进行分类过滤。比如,如果你想要找到可以帮助你开发应用的库,你可以展开 Intended Audience 并选择 Developers。另外,你可能还需要一个稳定且可用于生产的包,可以展开 Development Status 并选择 Production/Stable。
你可以应用其他过滤器以及调整搜索词,直到找到你想要的包。
搜索结果提供了一个包页面的链接,包含了更多的信息以及想要的文档。下面我们看看 requests-oauth2 的信息:
这个项目页面提供了更多的信息,而且看起来还有一个指向 Home 页的链接。该链接指向 Github 上的项目仓库。你可以看到项目相关的更多信息以及一些使用示例。
看到初始源代码仓库,像是找到了无价的财富。在那里,你可以通过查看最新的提交日志,PR(pull request)次数以及打开的 issues 等问题来找到一些项目的状态和提示。
另外还有一个查找包的方式,Google。被广泛使用的 Python 库会展示在 google 搜索的顶部,并且你应该能看到指向 PyPI 中包或者源代码仓库的链接。
找到一个合适包需要花费一些时间研究,但是只要找到了,就可以为你的开发过程提速。
卸载包
有时候你不得不卸载一个软件包。要么是你找到了一个更好的包来替代它,要么是确实不需要某些功能了。卸载软件包会有一些棘手。
注意这里,当你安装了 requests,pip 同时也安装了其他的依赖。你安装的包越多,多个包拥有相同的依赖的可能性越大。这里 pip 的 show 命令就派上用场了。
卸载包之前,先确保你已经对这个包运行了 show 命令:
[图片上传失败...(image-63734b-1565242498214)]
注意最后的两个属性 Requires 和 Required-by。show 命令向我们展示了 requests 需要依赖 urllib3,certifi,chardet 和 idna。你可能希望卸载其中的两个。而且你可以看到 requests 没有被其他包引用,所以它可以安全地卸载。
你应该对 requests 中所有的依赖都运行一下 show 命令,以确保没有其他库依赖它们。你了解了这些依赖次序之后,就可以使用 uninstall 命令来卸载它们。
卸载包会显示将要删除的文件并要求确认。如果你确认要卸载这个包并且已经检查了它的依赖关系,知道没有其他包在使用这个包,那么可以使用 -y 开关来隐藏文件列表和确认提示信息:
你可以一次调用指定所有你想卸载的包:
你还可以通过提供 -r 选项来删除需求文件中列出的全部软件包。这个命令会对每一个包都提示确认信息,如果你已经明确知晓你的操作,可以通过 -y 开关禁止这些提示:
在你想要卸载包时,一直都要记得检查一遍依赖项。你可能希望卸载一个软件包的所有依赖,不过如果有其它软件包在使用这些依赖,会导致程序崩溃。
pip 的替代品
pip 是所有 Pythonista 必备的基本工具,很多应用程序和项目使用它作为软件包管理器。本教程帮助你了解基础知识,而 Python 社区非常积极的为其它开发人员提供了很棒的工具和库。其中包括 pip 的替代品,期望实现简单高效的包管理。
在本节,你将了解到 Python 中其它可用的包管理工具。
万能的 Conda
Conda 是一个包括 Python 在内的多种语言的包、依赖及环境管理器。实际上,它最早来源于 Anaconda,作为 Python 中研究数据科学的包出现。
Conda 广泛用于数据科学和机器学习应用程序,并使用自己的索引来托管兼容的软件包。
Conda 不仅可以管理包的依赖项,还可以管理应用的虚拟环境,安装兼容并存的 Python 版本,为生产部署打包应用。
在 Windows 系统上为机器学习设置 Python 很好的介绍了 Conda,它探讨了包和环境管理。唯一与 Windows 相关的特定信息是安装,因此如果你使用的是其他系统平台,它仍然是可信的。
Pipenv
Pipenv 是另外一种包管理工具,旨在为 Python “提供全世界最好的包”。由于将虚拟环境与包管理合并到一个工具中,pipenv 在 Python 社区获得了极大的关注。
它还解决了在使用 pip 手动管理依赖关系是遇到的一些常见问题,比如,包的版本,隔离开发与生产环境依赖,锁定生产环境版本等。
Pipenv:新的 Python 打包工具指南是一份很好的学习 Pipenv 及其包管理的入门材料。尽管这篇文章的标签是中级,但是作者对读者做了很好的引导,初学 Python 的人也能理解这篇文章。
Poetry
Poetry 是另一个受到大量关注的 pip 替代品。与 Pipenv 类似,它简化了包的版本管理并隔离了开发环境与生产环境的依赖,而且它将依赖隔离到一个虚拟环境中运行。
如果你已经了解 JavaScript 和 npm,会觉得 Poetry 非常熟悉。它不只是管理包,还可以帮助你为应用和库构建发行版本并部署到 PyPI。如何向 PyPI 发布一个开源的 Python 包中一个很棒的 Poetry 介绍可以帮你入门。
总结:什么是 pip?
本教程回答了问题:什么是 pip?你现在已经知道,pip 是 Python 的包管理器,被很多项目用于依赖管理。现在 Python 安装器已经包含了 pip,使它成为所有的 Pythonista 都应当会用的基础工具。
Python 提供了一个适用于开发各种应用的标准库扩展,但是 Python 活跃的社区提供了更多的工具和库,可以加速 Python 应用开发。
这些工具和库都发布在 Python 包索引(PyPI)上,并且使用 pip 允许开发者在自己的环境中安装它们。
通过这篇教程,你可以学到:
1. 在命令行使用 pip 以及需求文件安装新的软件包
2. 管理依赖,隔离开发与生产环境,以及创建一个锁定的需求文件
3. 通过 pip 和 PyPI 查找包
4. 在卸载包之前评估包依赖,以及如何卸载包此外,你已经了解到保持依赖处于最新的重要性,而且,pip 的很多替代品可以帮你管理这些依赖。
如果你有任何问题,可以随时在下面的评论部分留言,你还可以随时在 pip 文档页面获取更多信息。
英文原文:https://realpython.com/what-is-pip/译者:敦伟
注:我这有个学习Python基地,里面有很多学习资料,感兴趣的+Q群:895817687