Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 453 – Python 安装中 pip 的显式引导

作者:
Donald Stufft <donald at stufft.io>, Alyssa Coghlan <ncoghlan at gmail.com>
BDFL 委托
Martin von Löwis
状态:
最终版
类型:
标准跟踪
创建日期:
2013年8月10日
发布历史:
2013年8月30日,2013年9月15日,2013年9月18日,2013年9月19日,2013年9月23日,2013年9月29日,2013年10月13日,2013年10月20日
决议:
Python-Dev 消息

目录

摘要

本 PEP 提议更新 Python 2.7、3.3 和 3.4 中的 安装 Python 模块 指南,以正式推荐使用 pip 作为 Python 包的默认安装程序,并对 Python 3.4 进行适当的技术更改,以便默认提供 pip 以支持该建议。

PEP 接受

本 PEP 于2013年10月22日星期二被 Martin von Löwis 接受,纳入 Python 3.4。

Issue 19347 已创建,用于跟踪本 PEP 的实施。

基本原理

本 PEP 中的提案有两个相关但不同的理由。第一个与新用户的体验有关,第二个与更好地促进更广泛的 Python 打包生态系统的发展有关。

改善新用户体验

目前,在没有平台包管理器和存储库的系统上,将第三方 Python 包安装到全新安装的 Python 中,首先需要识别合适的包管理器,然后安装它。

即使在 _拥有_ 平台包管理器的系统上,它也不太可能包含 Python 包索引上可用的每个包,甚至当所需的第三方包可用时,平台包管理器中的正确名称可能也不清楚。

这意味着,为了有效地与 Python 包索引生态系统协作,用户必须知道要安装哪个包管理器,从哪里获取它,以及如何安装它。其结果是,第三方 Python 项目目前需要从各种不理想的替代方案中进行选择

  • 假设用户已经安装了合适的跨平台包管理器。
  • 复制说明并告诉他们的用户如何安装包管理器。
  • 完全放弃使用依赖项,以缓解用户安装问题。

所有这些可用的选项都有显著的缺点。

如果项目只是假设用户已经有了工具,那么初学者在安装命令不起作用时可能会收到令人困惑的错误消息。某些操作系统可能会通过提供一个全局钩子来缓解这种痛苦,该钩子会查找不存在的命令并建议他们可以安装的操作系统包,以使命令正常工作,但这只适用于拥有包含提供相关跨平台安装程序命令的包的平台包管理器的系统(例如许多主要的 Linux 发行版)。Windows 和 Mac OS X 用户,或更保守的 Linux 发行版,则没有这样的帮助。对于初学者(他们通常也完全不熟悉编程、命令行工具的使用和系统环境变量的编辑)来说,处理这个问题的挑战是核心 Python 开发人员从专业教育工作者和其他向新用户介绍 Python 的人那里收到的反馈中经常出现的问题。

如果一个项目选择复制安装说明,并在告诉用户如何安装自己的项目之前告诉他们如何安装包管理器,那么每当这些说明需要更新时,每个复制了它们的项目都需要更新。当有多个相互竞争的安装工具可用,并且不同项目推荐不同的工具时,这个问题尤其突出。

通过大力推广 pip 作为默认安装程序,并建议其他项目引用 pip 自己的引导说明 而不是复制它们,可以部分缓解这个问题。然而,这种方法创建的用户体验仍然不是特别好(尽管正在努力创建一个 pip 及其依赖项的组合 Windows 安装程序,这应该会改善该平台上的情况,而 Mac OS X 和 *nix 平台通常有 wget,因此能够轻松从命令行下载并运行引导脚本)。

那些决定完全放弃依赖关系的项目,要么被迫通过发明自己的解决方案来重复其他项目的努力,要么被迫简单地将其他项目包含在自己的源代码树中。这两种选择都带来了各自的问题,要么是在整个生态系统中重复维护工作,要么可能使用户容易受到安全问题的影响,因为包含的代码或重复的努力在上游发布新版本时不会自动更新。

通过正式推荐并默认提供特定的跨平台包管理器,用户在安装这些第三方包时会更容易,分发这些包的人也会更容易,因为他们现在应该可以安全地假设大多数用户将拥有合适的安装工具(或可以访问获取这些工具的明确说明)。随着 Wheel 包格式(特意)没有内置的 setup.py 形式的“安装程序”,用户即使在最简单的情况下也希望有安装程序,因此这预计在未来会变得更加重要。

减轻实际安装第三方包的负担也应减少将所有有用的模块添加到标准库的压力。这将使标准库的添加更多地关注 Python 为什么应该开箱即用地拥有特定工具,以及为什么该包采用标准库的 18-24 个月功能发布周期是合理的,而不是使用安装第三方包的普遍困难作为纳入的理由。

提供标准安装系统还有助于引导替代的构建和安装系统,例如 zc.buildouthashdistconda。只要 pip install <tool> 正常工作,那么标准的 Python 特定安装程序就提供了一个相当安全、跨平台的机制来获取这些实用程序。

促使更广泛的 Python 打包生态系统演进

由于没有新的打包标准能够实现广泛采用,如果没有涵盖广泛 _当前_ 使用的 Python 版本的过渡策略(而不仅仅是像大多数语言功能一样是未来版本),本 PEP 中提出的更改被认为是 Python 打包生态系统演进的必要步骤。

更广泛的社区已将 Python 包索引作为分发和安装 Python 软件的机制,但语言演进和安全软件分发的不同关注点意味着需要一个更快的包含旧版本的功能发布周期才能正确支持后者。

此外,核心 CPython 开发团队有幸在社区其他成员之前很早就放弃了对早期 Python 版本的支持,因为下游商业再分发商承担了为仍需要这些版本的用户提供支持的任务,而许多第三方库则在这些版本仍被广泛使用时保持兼容性。

这意味着,当前基于 setup.py install 的包安装模型给新打包标准的开发和采用带来了严重困难,因为,根据项目编写 setup.py 文件的方式,安装命令(以及其他操作)最终可能会调用标准库的 distutils 包。

作为一个指标,说明这可能给更广泛的生态系统带来问题,请考虑 Python 2.6 中 distutils 的功能集在 2008 年 6 月(随 Python 2.6b1 发布)被冻结,而 Python 2.7 中 distutils 的功能集在 2010 年 4 月(随 Python 2.7b1 发布)被冻结。

相比之下,使用像 pip 这样的独立安装程序(即使直接调用 distutilssetup.py 文件也仍然支持新的打包标准)使得在旧版本的 Python 中支持新的打包标准成为可能,只需升级 pip(大约每 6 个月发布一次新功能)。通过让最终用户更容易安装和升级更新的构建系统(如 setuptools)或改进的 PyPI 上传工具(如 twine),旧版本 Python 的情况得到了进一步改善。

并非巧合的是,这种使用具有更多元数据和较少活跃分发格式的独立安装程序的提议模型与大多数操作系统(包括自引入安装程序服务和 MSI 文件格式以来的 Windows)以及许多其他特定语言安装程序所使用的模型相匹配。

对于 Python 2.6,这种兼容性问题主要限于各种企业级 Linux 发行版(及其下游衍生版本)。这些发行版的更新周期通常比 CPython 更慢,因此它们为上游被视为“仅安全修复”版本的 Python 版本提供全面支持(有时甚至可能达到核心开发团队根本不再支持它们的程度——如果真的需要,你仍然可以获得 Python 2.3 的商业支持!)。

实际上,wgetcurl 等工具在 Linux 系统上随时可用,大多数 Linux 上的 Python 用户已经熟悉命令行,并且大多数 Linux 发行版都预装了使运行 Python 脚本变得容易的默认配置,这意味着任何 *nix 系统的现有 pip 引导说明已经相当简单明了。即使 pip 未由系统包管理器提供,那么使用 wgetcurl 从 www.pip-installer.org 获取引导脚本然后运行它,也只需要几个可以轻松复制粘贴的 shell 命令。

因此,对于任何 *nix 系统上的任何 Python 版本,在旧版本中引导 pip 的需求不被认为是采用新打包标准的主要障碍,因为它只是这些长期稳定版本的用户遇到的又一个小小的障碍。对于 *nix 系统,本 PEP 对 pip 作为首选默认打包工具的正式认可比使其默认可用的底层技术细节更为重要,因为它改变了 pip 开发人员与 pip 和 CPython 的下游重新打包者之间的对话性质。

另一方面,对于 Python 2.7,采用新元数据标准的兼容性问题更为普遍,因为它影响了 Windows 和 Mac OS X 的 python.org 二进制安装程序,以及即使是相对快速变化的 *nix 平台。

首先,与 Python 2.6 不同,Python 2.7 仍然是一个完全受支持的上游版本,并将一直保持到 Python 2.7.9 发布(目前计划于 2015 年 5 月),届时它预计将进入通常的“仅安全修复”模式。这意味着至少还有 19 个月,Python 2.7 是享受完全上游支持的 Python 应用程序的部署目标。即使核心开发团队在 2015 年将 2.7 切换到仅安全发布模式后,Python 2.7 仍可能在 2020 年之后仍然是商业支持的遗留目标。

虽然 Python 3 对于 _新的_ Python 应用程序和部署(没有对 Python 2 的现有投资,也没有对特定 Python 2 专用第三方模块的依赖——这组模块随着时间的推移变得越来越小)来说,已经提供了引人注目的替代方案,但要创建令人信服的商业案例来将现有的基于 Python 2.7 的基础设施更新到 Python 3,还需要更长的时间,特别是在自动化测试文化薄弱(或不存在)的情况下,这使得有效使用可用的迁移实用程序变得困难。

虽然本 PEP 仅提议对 Python 2.7 进行文档更改,但一旦 pip 有 Windows 安装程序可用,将创建并提交一个单独的 PEP,提议为未来的 CPython 2.7 维护版本创建和分发聚合安装程序,将 CPython、pip 和 Python Launcher for Windows 安装程序合并为一个下载(单独的下载仍将可用——聚合安装程序将作为一种便利提供,并明确指示 Windows 系统中 Python 的推荐操作环境)。

为什么选择 pip?

pip 已被选为首选的默认安装程序,因为它是一个已经很流行的工具,解决了其前身 easy_install 的几个设计和用户体验问题(由于向后兼容性问题,这些问题无法在 easy_install 本身中轻松修复)。pip 也非常适合在单个 Python 运行时安装(包括相关的虚拟环境)范围内工作,这是捆绑在 CPython 中的工具的一个理想特性。

其他工具,如 zc.buildoutconda,目标更为宏大(因此在处理外部二进制依赖方面比 pip 更好),因此 Python 生态系统将它们更多地视为平台包管理器来交互,而不是默认的跨平台安装工具,这是有道理的。这种关系类似于 pipaptyum 等平台包管理系统之间的关系(它们也旨在处理任意二进制依赖项)。

提案概述

本 PEP 提议更新 安装 Python 模块 指南,以正式推荐使用 pip 作为 Python 包的默认安装程序,而不是当前直接调用 setup.py install 命令的方法。

然而,为了避免推荐 CPython 不提供的工具,进一步提议在安装 CPython 3.4 或更高版本时,以及使用标准库的 venv 模块通过 pyvenv 命令行实用程序创建虚拟环境时,默认提供 pip 包管理器。

为此,本 PEP 提议在 Python 3.4 中包含一个 ensurepip 引导模块,并从 pyvenv 自动调用该模块,以及更改 Python 在 Windows 上处理已安装脚本的方式。使用引导模块而不是直接提供 pip 有助于明确划分开发职责,并避免在更新 CPython 时无意中降级 pip

为了给可能不从最新版本开始的 Python 新用户提供清晰的指导,本 PEP 还提议更新 Python 2.7 和 3.3 中的“安装 Python 模块”指南,以推荐安装和使用 pip,而不是直接调用 distutils。它_不_提议向后移植任何为 Python 3.4 提议的代码更改。

最后,PEP 还强烈建议 CPython 再分发商和其他 Python 实现确保默认提供 pip,或至少明确记录未包含的事实。

本 PEP _不_提议将 pip(或任何依赖项)直接作为标准库的一部分提供。相反,pip 将作为一个捆绑应用程序与 CPython 一起提供,以方便 Python 用户,但受其自身的开发生命周期约束,并且能够独立于核心解释器和标准库进行升级。

显式引导机制

将向标准库中添加一个名为 ensurepip 的附加模块,其目的是将 pip 及其任何依赖项安装到适当的位置(最常见的是 site-packages)。它将公开一个名为 bootstrap() 的可调用对象,并提供通过 python -m ensurepip 直接执行的功能。

引导程序_不_会联系 PyPI,而是依赖存储在标准库中的 pip 私有副本。因此,只支持与安装位置相关的选项(--user--root 等)。

为了利用正在进行的努力来提高基于 PyPI 的生态系统的安全性,并受益于提高该生态系统的速度、可靠性和灵活性的努力,强烈鼓励用户使用最新可用的 pip 版本被认为是可取的。

为了实现默认提供最新版 pip 的目标,pip 的私有副本将在 CPython 维护版本中更新,这应与 pip 新版本的 6 个月周期很好地契合。

安全考虑

本 PEP 中的设计是故意选择的,以避免对最终用户运行 pip install --upgrade pip 命令后 CPython 的信任模型进行任何重大更改。

安装程序将包含一个完全功能的 Python 版本的所有组件,包括 pip 安装程序。安装过程_不_需要网络访问,也_不_依赖于信任 pip 与 Python 包索引之间建立的网络连接的安全性。

只有选择使用 pip 与 PyPI 通信的用户才需要关注由此带来的额外安全考虑。

然而,核心 CPython 团队仍将协助审查和解决目前影响 requests 项目(以及因此影响 pip)的 证书更新管理问题,并可能提供帮助解决其他已识别的安全问题 [1]

可靠性考虑

通过将引导程序作为标准库的一部分(而不仅仅是二进制安装程序的一个功能),可以轻松地使用现有的 CPython buildbot 基础设施测试引导命令的正确操作,而不是显著增加安装程序本身的测试负担。

实施策略

为确保在安装 Python 或创建虚拟环境时无需网络访问,ensurepip 模块将作为实现细节,包含 pip 及其依赖项的完整私有副本,该副本将用于提取 pip 并将其安装到目标环境中。需要强调的是,pip 的这个私有副本_仅仅_是实现细节,除了通过 ensurepip 模块(以及间接通过 venv)公开的公共功能之外,不应依赖或假定其存在。

目前还没有 ensurepip 的参考实现。现有的 get-pip.py 引导脚本展示了通用概念的早期变体,但标准库版本将利用 CPython 安装程序提供的改进分发功能,以 wheel 文件形式包含 pipsetuptools 的私有副本(而不是嵌入式 base64 编码数据),并且不会尝试联系 PyPI(而是直接从私有 wheel 文件安装)。

不是包含单独的代码来处理引导,而是 ensurepip 模块将适当地操作 sys.path,以允许 wheel 文件用于安装自身,无论是安装到当前的 Python 安装中还是安装到虚拟环境中(由传递给引导命令的选项决定)。

建议分五个独立步骤实施(前两个步骤之后的所有步骤都是相互独立的,可以以任何顺序执行)。

  • 第一步将更新“安装 Python 模块”文档,以推荐使用 pip 并引用 pip 团队的下载和安装说明。此更改将应用于 Python 2.7、3.3 和 3.4。
  • ensurepip 模块以及 pip 和 setuptools 最新发布版本的私有副本添加到 Python 3.4,并相应更新 3.4 的“安装 Python 模块”文档。
  • CPython Windows 安装程序将更新,以提供 Python 3.4 的新 pip 安装选项。
  • CPython Mac OS X 安装程序将更新,以提供 Python 3.4 的新 pip 安装选项。
  • 在 Python 3.4 中,venv 模块和 pyvenv 命令将更新,以使用 ensurepip
  • Windows 上的 PATH 处理将更新为 Python 3.4+。

整合时间表

如果本 PEP 被接受,将 pip 整合到 CPython 版本中的提议时间框架如下:

  • 在 3.4.0 alpha 4 发布后尽快
    • 根据 pip 1.5 的预发布版本更新文档并实现 ensurepip
    • 已实现 Python 3.4 的所有其他提议功能更改,包括调用 ensurepip 的安装程序更新。
  • 11月20日(比3.4.0 beta 1的计划发布日期提前3天)
    • ensurepip 已更新为使用 pip 1.5 发布候选版本。
    • PEP 101 已更新,涵盖确保捆绑的 pip 版本是最新的。
  • 11月24日(3.4.0 beta 1 的预定发布日期)
    • 与其他新功能一样,所有针对 Python 3.4 的提议功能更改都必须在 beta 功能冻结之前实施。
  • 12月29日(比3.4.0 beta 2的预定发布日期提前1周)
    • requests 证书管理问题已解决。
    • ensurepip 已更新到 pip 1.5 的最终发布版本,或后续的维护版本(包括适当更新的捆绑副本 requests)。

(有关每个发布的当前官方预定日期,请参阅 PEP 429。上面列出的日期截至 2013 年 10 月 20 日是准确的。)

如果 pip 1.5 的最终或维护版本(包含适当更新的 requests 版本)在计划的 Python 3.4 beta 2 发布前一周仍不可用,则本 PEP 的实施将推迟到 Python 3.5。请注意,这种情况被认为不太可能发生——pip 1.5 发布的暂定日期目前是 12 月 1 日。

在未来的 CPython 发布中,这种协调调度应该不再需要:CPython 发布经理将能够直接更新到最新发布的 pip 版本。然而,在这种情况下,pip 中需要一些修复才能使捆绑正常工作,并且需要改进 requests 的证书更新机制,因此 pip 1.5 发布周期需要与 CPython 3.4 beta 发布正确对齐。

提议的 CLI

提议的 CLI 基于现有 pip install 选项的一个子集。

Usage:
  python -m ensurepip [options]

General Options:
  -h, --help          Show help.
  -v, --verbose       Give more output. Option is additive, and can be used up to 3 times.
  -V, --version       Show the pip version that would be extracted and exit.
  -q, --quiet         Give less output.

Installation Options:
  -U, --upgrade       Upgrade pip and dependencies, even if already installed
  --user              Install using the user scheme.
  --root <dir>        Install everything relative to this alternate root directory.

在大多数情况下,最终用户不需要直接使用此 CLI,因为 pip 应该在安装 Python 或创建虚拟环境时已自动安装。但是,它作为公共接口正式记录,以支持至少以下已知用例:

  • Windows 和 Mac OS X 安装,其中安装过程中_未_选择“安装 pip”选项。
  • 用户之前运行过“pip uninstall pip”的任何安装。

希望从 PyPI 获取最新版本或需要更多灵活性的用户,可以适当地调用提取出的 pip

提议的模块 API

提议的 ensurepip 模块 API 由以下两个函数组成:

def version():
    """
    Returns a string specifying the bundled version of pip.
    """

def bootstrap(root=None, upgrade=False, user=False, verbosity=0):
    """
    Bootstrap pip into the current Python installation (or the given root
    directory).
    """

从 CPython 安装程序中调用

CPython Windows 和 Mac OS X 安装程序将各增加一个新选项:

  • 安装 pip(默认的 Python 包管理实用程序)?

此选项将默认选中。

如果选中此选项,安装程序将使用刚刚安装的 Python 调用以下命令:

python -m ensurepip --upgrade

这确保了默认情况下,安装或更新 CPython 将确保所安装的 pip 版本至少与该 CPython 版本中包含的版本一样新。如果已经安装了较新的 pip 版本,则 python -m ensurepip --upgrade 将简单地返回而不做任何事情。

从源代码安装

正如预构建的二进制安装程序将默认更新以运行 python -m ensurepip 一样,源代码分发的 make installmake altinstall 命令也将进行类似更改。sysconfig 模块中的目录设置应确保 pip 组件自动安装到预期位置。

ensurepip 本身(包括 pip 及其依赖项的私有副本)将始终正常安装(因为它是标准库的常规部分),但将提供一个选项来跳过 ensurepip 的调用。

这意味着即使从源代码安装也将默认提供 pip,但通过其他方式提供 pip(或根本不提供)的再分发商仍可以通过 ensurepip 选择不安装它。

虚拟环境的变更

Python 3.3 通过 venv 模块包含了一种用于虚拟 Python 环境的标准库方法。自发布以来,很明显很少有用户愿意直接使用此功能,部分原因是虚拟环境中默认缺少安装程序。相反,他们选择继续使用 virtualenv 包,该包_确实_默认安装了 pip。

为了使 venv 对用户更有用,它将被修改为在创建新环境时默认在其内部引导 pip。这将使人们在虚拟环境中获得与本 PEP 在虚拟环境之外提供的相同便利,并将 venv 模块与外部 virtualenv 包的功能更接近,使其成为更合适的替代品。

为了处理用户不希望将 pip 引导到其虚拟环境中的情况,将添加一个 --without-pip 选项。

venv.EnvBuildervenv.create API 将更新以接受一个新参数:with_pip(默认为 False)。

选择模块 API 的新默认值是为了向后兼容当前行为(因为假定 venv 模块的大多数调用都是通过第三方工具发生的,这些工具可能不希望在未明确请求的情况下安装 pip),而选择命令行接口的默认值是为了确保 pip 在大多数虚拟环境中可用,而无需最终用户进行额外操作。

由于此更改仅适用于 Python 3.4 及更高版本,因此仍需要第三方 virtualenv 项目才能在 Python 3.3 和 2.7 中获得一致的跨版本体验。

文档

Python 2.7、3.3 和 3.4 标准库文档的“安装 Python 模块”部分将更新,以推荐使用 pip 安装程序,该安装程序在 Python 3.4 中默认提供,或由用户在 Python 2.7 或 3.3 中检索和安装。它将简要描述最常见的命令和选项,但将完整详细信息委托给外部维护的 pip 文档。

在 Python 3.4 中,pyvenvvenv 文档也将更新,以引用修订后的模块安装指南。

模块安装指南的现有内容将在所有版本中保留,但将放在一个新的“直接调用 distutils”子部分下。

将 CA 证书与 CPython 捆绑

ensurepip 实现将包含 pip CA 捆绑包以及 pip 的其余部分。这意味着 CPython 实际上包含了一个仅供 pip 提取后使用的 CA 捆绑包。

这被认为优于仅依赖系统证书存储,因为它确保 pip 在所有受支持的 Python 版本中行为一致,即使是那些在 Python 3.4 之前无法访问 Windows 上的系统证书存储的版本。

自动安装 setuptools

pip 当前依赖 setuptools 来处理构建过程中的元数据生成以及其他一些功能。虽然正在努力减少或消除这种依赖关系,但尚不清楚这项工作是否能在 pip 1.5(Python 3.4.0 发布时可能为当前版本)完成。

本 PEP 提议,如果 pip 仍然需要它作为依赖项,ensurepip 将包含 setuptools 的私有副本(除了 ensurepip 的私有副本)。然后 python -m ensurepip 将在安装 pip 本身的同时安装私有副本。

然而,这种行为被正式认为是实现细节。其他明确需要 setuptools 的项目仍然必须提供适当的依赖声明,而不是假定 setuptools 将始终与 pip 一起安装。

一旦 setuptools 的私有副本不再需要,它将从 ensurepip 中删除。这可能发生在 get-pip.py 停止默认安装 setuptools 的时候。只要需要 setuptools,它将是最新上游 setuptools 发布的完全未修改副本,包括 easy_install 脚本(如果上游 setuptools 继续包含它)。将 easy_installpip 一起安装并不被认为是理想的,但安装损坏的 setuptools 会更糟。一旦 pip 开发人员成功消除对 setuptools 的依赖,并且 setuptools 的私有副本可以完全从 CPython 中删除,这个问题将自然解决。

更新 pip 的私有副本

为了跟上打包的演变并为用户提供尽可能新的版本,ensurepip 模块将定期更新,以包含它引导的所有最新版本。

在每次 pip 新发布后,以及在准备任何 Python 发布(包括功能发布)期间,将运行作为本 PEP 实现一部分提供的脚本,以确保 CPython 源代码存储库中存储的私有副本已更新到最新版本。

更新 ensurepip 模块 API 和 CLI

venvpyvenv 一样,ensurepip 模块 API 和 CLI 将受标准库的正常规则约束:维护版本中不允许添加新功能。

然而,如上所述,嵌入式组件可能会更新,因此提取出的 pip 可能会在维护版本中提供附加功能。

卸载

本 PEP 未提议对 CPython 卸载过程进行任何更改。引导的 pip 将以与任何其他 pip 安装的包相同的方式安装,并将以与 Python 环境的任何其他后期安装添加相同的方式处理。

至少在 Windows 上,这意味着引导文件将在卸载后保留下来,因为这些文件不会与 Python MSI 安装程序关联。

虽然可以提出 CPython 安装程序自动清理这些目录的理由,但更改这种行为被认为超出了本 PEP 的范围。

在 Windows 上执行脚本

虽然 Python 3.3 中更新了 Windows 安装程序,以可选地使 python 在 PATH 上可用,但没有进行此类更改以包含由 sysconfig.get_path("scripts") 返回的脚本安装目录。

因此,除了在安装过程中添加提取和安装 pip 的选项外,本 PEP 提议更新 Python 3.4 及更高版本中的 Windows 安装程序,以便在安装过程中启用 PATH 修改选项时,也将 sysconfig.get_path("scripts") 返回的路径添加到 Windows PATH 中。

请注意,此更改仅在 Python 3.4 及更高版本中可用。

这意味着,对于 Python 3.3,在 Windows 上全局调用 pip 最可靠的方式(无需手动修改 PATH)仍然是 py -m pip(或 py -3 -m pip,如果同时安装了 Python 2 和 3,则选择 Python 3 版本),而不是简单地调用 pip。这之所以有效,是因为 Python 3.3 默认提供了 Windows 的 Python 启动器(以及相关的 py 命令)。

对于 Python 2.7 和 3.2,最可靠的机制是使用独立安装程序安装 Windows 的 Python 启动器,然后如上所述使用 py -m pip

将脚本目录添加到系统 PATH 意味着 pip 在“系统 PATH 上只有一个 Python 安装”的情况下可以可靠地工作,而 py -m pippipXpipX.Y 仅在并行安装情况(并且在虚拟环境之外)下才需要选择非默认版本。此更改还应使 pyvenv 命令以及 pipeasy_install 和类似工具安装的所有脚本在 Windows 上更容易调用。

虽然最近版本的 Python 中的脚本调用将通过 Windows Python 启动器运行,但这不应引起任何问题,只要 Scripts 目录中的 Python 文件在其 shebang 行中正确指定了 Python 版本,或者具有相邻的 Windows 可执行文件(如 easy_installpip)。

对下游分销商的建议

Python 安装的常见来源是通过下游分销商,例如各种 Linux 发行版 [3] [4] [5],OSX 包管理器 [6] [7] [8],以及商业 Python 再分发商 [9] [10] [11]。为了向所有 Python 用户提供一致、用户友好的体验,无论他们如何获得 Python,本 PEP 建议并要求下游分销商:

  • 确保每当安装 Python 时,pip 要么已安装,要么以其他方式方便最终用户使用。
    • 对于使用二进制安装程序的再分发商,这可能以在安装期间可选执行 ensurepip 引导的形式出现,类似于 CPython 安装程序。
    • 对于使用包管理系统的再分发商,这可能采取相互依赖的单独包的形式,以便安装 Python 包会安装 pip 包,而安装 pip 包会安装 Python 包。
    • 另一种合理的实现方式是单独打包 pip,但确保有一个全局钩子,当用户在未安装 pip 的情况下执行 pip 时,会建议安装单独的 pip 包。选择此选项的系统应确保 ensurepip 模块在虚拟环境中调用时仍直接安装 pip,但可能会修改系统 Python 安装中的模块,以便在全局安装 pip 时重定向到平台提供的机制。
  • 即使 pip 通过其他方式在全球范围内可用,也不要删除 Python 3.4 或更高版本中的 ensurepip 模块。
    • ensurepip 将用于 venv 模块自动将 pip 安装到虚拟环境中。
    • 这类似于现有的 virtualenv 包,许多下游分销商已经为它破例了常见的“解捆”政策。
    • 这意味着,如果需要因安全问题更新 pip,那么 ensurepip 引导模块中的私有副本也需要更新。
    • 然而,更改 pip 的私有副本以删除嵌入式 CA 证书捆绑包并转而依赖系统 CA 捆绑包是合理的更改。
  • 确保本 PEP 的所有功能在对重新分发版本的 Python 进行任何修改后仍能正常工作。
    • 使用 python -m ensurepip --versionensurepip.version() 检查将要引导的 pip 版本。
    • 使用 python -m ensurepipensurepip.bootstrap() 将 pip 安装到全局或虚拟 python 环境中。
    • 全局安装中的 pip install --upgrade pip 不应影响任何已创建的虚拟环境(但允许影响未来的虚拟环境,尽管在使用 ensurepip 的标准实现时不会这样做)。
    • 虚拟环境中的 pip install --upgrade pip 不应影响全局安装。
  • 在可行的情况下,迁移构建系统以利用 pipWheel,并避免直接调用 setup.py
    • 这将有助于确保随着 Python 打包生态系统的不断发展,向改进的元数据格式进行更顺畅、更及时的迁移。

如果 Python 再分发商选择_不_遵循这些建议,我们要求他们明确记录这一事实,并向用户提供关于将上游基于 pip 的安装说明转换为适合平台说明的适当指导。

其他 Python 实现也鼓励在适用情况下遵循这些准则。

政策与治理

引导软件的维护者和 CPython 核心团队将共同努力,以满足双方的需求。引导软件仍将独立于 CPython,本 PEP 不包括 CPython 承担引导软件的开发职责或设计决策。本 PEP 旨在减轻希望使用第三方包的最终用户的负担,其中的决策是务实的,代表了 Python 社区已经对 Python 打包机构(作为 pipsetuptools、PyPI、virtualenv 和其他相关项目的作者和维护者)的信任。

向后兼容性

ensurepip 模块本身的公共 API 和 CLI 将遵循 Python 标准库的典型向后兼容性政策。本 PEP 捆绑的外部开发软件则不遵循此政策。

最重要的是,这意味着引导版本的 pip 可以在 CPython 维护版本中获得新功能,并且 pip 继续按照其自己的 6 个月发布周期运行,而不是 CPython 的 18-24 个月周期。

安全发布

任何影响 ensurepip 模块的安全更新都将在发布前与 Python 安全响应团队(security@python.org)共享。然后,PSRT 将决定报告的问题是否需要发布 CPython 的安全版本,并更新 pip 的私有副本。

许可

pip 目前以 1 Clause BSD 许可,它包含来自其他项目的代码。此外,本 PEP 将包含 setuptools,直到 pip 不再需要它为止。这些许可在下表中列出。

项目 许可
请求 Apache 2.0
six 1 Clause BSD
html5lib 1 Clause BSD
distlib PSF
colorama 3 Clause BSD
Mozilla CA 捆绑包 LGPL
setuptools PSF

所有这些许可证都应该与 PSF 许可证兼容。此外,目前尚不清楚 CA 捆绑包是否受版权保护,因此是否需要或可以授权。

附录:被拒绝的提案

更改 Windows 上脚本目录的名称

本 PEP 的早期版本提议将 Windows 上脚本安装目录的名称从“Scripts”更改为“bin”,以改善 pyvenv 创建的虚拟环境的跨平台一致性。

然而,Paul Moore 认为此更改可能与使用以前版本的 Python 创建的跨版本 Windows 安装程序向后不兼容,因此此更改已从本 PEP 中删除 [2]

在 Python 2.7 和 3.3 中包含 ensurepip

本 PEP 的早期版本认为,为新用户引导 pip 的挑战对 Python 未来增长构成了足够的障碍,因此有理由将 ensurepip 作为新功能添加到即将发布的 Python 2.7 和 3.3 维护版本中。

虽然在 Python 3.4 中提供 pip 的提案普遍受到欢迎,但该提案的这一部分备受争议,最终被 MvL 作为 BDFL 委托人拒绝

因此,将 ensurepip 反向移植到 Python 2.7 和 3.3 的提案已从本 PEP 中删除,取而代之的是为 pip 创建一个 Windows 安装程序,以及可能在未来提出一个 PEP,建议为 Python 2.7 创建一个聚合安装程序,将 CPython 2.7、pip 和 Python Launcher for Windows 结合起来。

引导 pip 时自动联系 PyPI

本 PEP 的早期版本将引导模块称为 getpip,并默认从 PyPI 下载并安装 pip,私有副本仅作为备用选项或在明确请求时使用。

这导致了几个复杂的边缘情况,以及难以定义引导模块的清晰 API 和 CLI。它还显著改变了 python.org 上发布的二进制安装程序的默认信任模型,因为最终用户需要明确 _选择退出_ 信任 PyPI 生态系统的安全性(而不是通过在安装后明确调用 pip 来选择加入)。

因此,PEP 被简化为当前设计,即引导始终使用 pip 的私有副本。联系 PyPI 现在始终是明确的单独步骤,可以直接访问完整的 pip 接口。

移除隐式尝试访问 PyPI 也使得在从自定义源代码构建安装时默认调用 ensurepip 成为可能。

隐式引导

PEP 439,本 PEP 的前身,提出了自己的解决方案。其解决方案涉及发布一个假的 pip 命令,当执行时,如果 pip 不存在,则会隐式引导和安装 pip。这被拒绝了,因为它过于“神奇”。它向最终用户隐藏了 pip 命令何时安装或是否正在安装。它也没有为希望通过其系统典型机制管理全局安装的 pip 的下游打包商提供任何建议或考虑。

隐式引导机制还遇到了可能的权限问题,如果用户无意中尝试引导 pip 但没有对适当安装目录的写入权限。

将 pip 直接包含在标准库中

与本 PEP 类似的是,提议将 pip 直接包含在标准库中。这将确保 Python 始终包含 pip,并解决默认情况下没有 pip 所面临的所有最终用户问题。这已被拒绝,因为我们通过标准库中 distutils 的包含和历史教训,认识到失去独立更新打包工具的能力可能使工具处于持续的停滞状态。这使得任何新功能在_多年_内都无法普遍可用,从而无法在实际影响用户的时间框架内合理演进。

允许打包工具独立于 Python 发布和采用计划发展,可以使改进被 Python 社区的 _所有_ 成员使用,而不仅仅是那些能够生活在 Python 最新版本边缘的人。

过去也存在“双重维护”问题,即一个项目在外部继续维护的同时,_也_在标准库中有一个分支。由于总是需要外部维护 pip 以支持早期 Python 版本,因此提议的引导机制将成为 CPython 核心开发人员(在 pip 开发人员的协助下)的明确责任,而报告给 CPython 跟踪器的 pip 问题将迁移到 pip 问题跟踪器。毫无疑问,用户仍然会对使用哪个跟踪器感到困惑,但希望比历史上将第三方项目的完整公共副本包含在标准库中时所见的情况要少。

本 PEP 中描述的方法还避免了一些技术问题,这些问题与在 pip 已独立更新到较新版本时处理 CPython 维护更新有关。提议的基于 pip 的引导机制自动处理了这个问题,因为 pip 和系统安装程序从不就谁拥有 pip 安装而发生冲突(它始终通过 pip 进行管理,无论是直接还是通过 ensurepip 引导模块间接管理)。

最后,单独的引导步骤意味着,如果最终用户希望,也可以轻松避免安装 pip。如果集成商使用系统软件包来处理使用一组通用工具以多种语言编写的组件的安装,通常就是这种情况。

默认为 –user 安装

曾考虑默认将 pip 引导到每个用户的 site-packages 目录中。然而,这种行为会令人惊讶(因为它不同于 pip 本身默认行为),并且目前也不被认为是可靠的(在将 pip 安装到用户 site-packages 目录而不是系统 site-packages 目录时,存在一些未正确处理的边缘情况)。

参考资料


来源:https://github.com/python/peps/blob/main/peps/pep-0453.rst

上次修改时间:2025-02-01 08:55:40 GMT