PEP 527 – 从 PyPI 中移除未(被)使用文件类型/扩展名
- 作者:
- Donald Stufft <donald at stufft.io>
- BDFL 代表:
- Alyssa Coghlan <ncoghlan at gmail.com>
- 讨论列表:
- Distutils-SIG 列表
- 状态:
- 最终
- 类型:
- 标准跟踪
- 主题:
- 打包
- 创建:
- 2016 年 8 月 23 日
- 发布历史:
- 2016 年 8 月 23 日
- 决议:
- Distutils-SIG 消息
摘要
本 PEP 建议弃用并最终移除对上传某些未使用或使用较少的文件类型和扩展名到 PyPI 的支持。特别是,它建议不再允许上传任何类型为 bdist_dumb
、bdist_rpm
、bdist_dmg
、bdist_msi
和 bdist_wininst
的文件,使 PyPI 只接受 sdist
、bdist_wheel
和 bdist_egg
文件类型的文件上传。
此外,本 PEP 还建议不再支持使用 .tar
、.tar.bz2
、.tar.xz
、.tar.Z
、.tgz
、.tbz
和除 .tar.gz
和 .zip
之外的任何其他扩展名的 sdist 文件进行上传。
最后,本 PEP 还建议将 PyPI 上每个项目的每个版本的 sdist 上传数量限制为一个,而不是每个允许的扩展名一个。
基本原理
文件格式
目前 PyPI 支持以下文件类型
sdist
bdist_wheel
bdist_egg
bdist_wininst
bdist_msi
bdist_dmg
bdist_rpm
bdist_dumb
但是,这些不同类型的文件在生态系统中的实用性或通用性各不相同。继续支持它们会增加 PyPI 以及工具作者的维护负担,并导致带宽和磁盘空间成本的增加,这不仅发生在 PyPI 本身,还发生在 PyPI 的任何镜像上。
Python 打包是一个多层次的生态系统,其中 PyPI 主要适合并用于从各自的项目所有者那里直接分发与虚拟环境兼容的软件包。然后,这些软件包要么由最终用户直接使用,要么由下游分发者使用,这些分发者获取这些软件包并将其转换为各自的系统级软件包(例如 RPM、deb、MSI 等)。
虽然 PyPI 本身仅直接处理这些特定于 Python 但与平台无关的软件包,但我们鼓励社区驱动和商业转换这些软件包到特定目标环境的下游格式,例如
- conda 跨平台数据分析生态系统 (conda-forge)
- 基于 deb 的 Linux 生态系统 (Debian、Ubuntu 等)
- 基于 RPM 的 Linux 生态系统 (Fedora、openSuSE、Mageia 等)
- Mac OS X 的 homebrew、MacPorts 和 fink 生态系统
- Windows 包管理生态系统 (NuGet、Chocolatey 等)
- 第三方创建 Windows MSI 和安装程序(例如 Christoph Gohlke 在 http://www.lfd.uci.edu/~gohlke/pythonlibs/ 上的工作)
- 其他商业重新分发格式(ActiveState 的 PyPM、Enthought Canopy 等)
- 其他开源社区重新分发格式(Nix、Gentoo、Arch、*BSD 等)
本 PEP 认为,整个生态系统可以通过保持 PyPI 专注于与平台无关的格式来获得最佳支持,志愿者有限的时间可以最好地用于此,而不是分散到多个平台上。此外,本 PEP 认为,最适合为特定平台提供良好集成软件包的人员是专注于该平台的人员,而不是所有可能的平台。
bdist_dumb
顾名思义,bdist_dumb
不是一种非常复杂的格式,但它过于简单以至于在实际使用中毫无价值。
例如,如果您在 macOS 上使用 pyenv 并使用 Python 3.5 构建库,那么 bdist_dumb
将生成一个名为 exampleproject-1.0.macosx-10.11-x86_64.tar.gz
的 .tar.gz
文件。这个文件名一开始就很难与 sdist
区分,因为它们都使用相同的扩展名(并且在旧的 PEP 440 版本之前,1.0-macosx-10.11-x86_64
是一个有效的,尽管很愚蠢的,版本号)。但是,一旦您打开创建的 .tar.gz
文件,您会发现里面没有元数据可以用于依赖项发现等,事实上,它只是一个 tarball,其中包含硬编码的路径到创建 bdist_dumb
的计算机上文件将被安装到的位置。回到我们 macOS 上的 pyenv 示例,这意味着如果我创建了它,它将包含以下文件:
Users/dstufft/.pyenv/versions/3.5.2/lib/python3.5/site-packages/example.py
bdist_rpm
PyPI 上的 bdist_rpm
格式允许用户上传 .rpm
文件,以便最终用户手动下载并手动安装。但是,rpm
的常见用法是使用一个专门设计的存储库,该存储库允许自动安装依赖项、升级等,而 PyPI 不提供这些功能。因此,它是一种在 PyPI 上几乎没有被使用的文件类型,只有大约 460 个此类文件被上传到 PyPI(总共 662,544 个)。
此外,像 COPR 这样的服务提供了比我们可能在 PyPI 上获得的更好的支持的发布和使用 RPM 文件的机制。
bdist_dmg、bdist_msi 和 bdist_wininst
bdist_dmg
、bdist_msi
和 bdist_winist
格式类似,因为它们是特定于操作系统的安装程序,只会将库安装到环境中,而不是为应用程序的真实用户界面安装而设计的(这将需要捆绑 Python 解释器等)。
在这三个中,bdist_dmg
和 bdist_msi
的使用率非常低,只有大约 500 个 bdist_msi
文件和大约 50 个 bdist_dmg
文件被上传到 PyPI。 bdist_wininst
格式的使用率更高,大约有 14,000 个文件被上传到 PyPI。
可以很容易地观察到 bdist_dmg
和 bdist_msi
的使用率很低,并得出移除它们的影响很小的结论,但是 bdist_wininst
的使用率高出几个数量级。但这有点误导,因为尽管有更多人上传这些文件,但实际上传文件的实际使用率却很低。查看过去 30 天,我们可以看到,从 PyPI 下载的所有 bdist_winist
文件中,90% 是由镜像基础设施生成的,7% 是由 setuptools 生成的(目前可以通过 bdist_egg
文件更好地覆盖)。
鉴于 bdist_dmg
和 bdist_msi
上传的文件数量很少,并且 bdist_wininst
主要存在于要么通过镜像基础设施消耗带宽和磁盘空间或者可以轻松地替换为 bdist_egg
,本 PEP 建议将这三种格式包含在要禁止的格式列表中。
文件扩展名
目前 sdist
支持各种各样的文件扩展名,如 .tar.gz
、.tar
、.tar.bz2
、.tar.xz
、.zip
、.tar.Z
、.tgz
和 .tbz
。但是,在这些扩展名中,只有 .tar.gz
(目前有 444,338 个 sdist)、.zip
(目前有 58,774 个 sdist)和 .tar.bz2
(目前有 3,265 个 sdist)的使用率超过了可忽略不计的水平。
接受多种格式需要 PyPI 内部和 PyPI 外部的工具来处理所有可能使用的各种扩展名(即使目前没有人使用它们)。这不仅影响 PyPI,而且波及整个生态系统。此外,不同的格式对 Python 链接到的可选 C 库以及它们支持的 Python 版本都有不同的要求。此外,多种格式还会造成一种奇怪的情况,即同一个项目/版本的两个 sdist
文件可能具有细微不同的内容。
很容易主张任何除了 .tar.gz
、.zip
和 .tar.bz2
之外的扩展名都应该被禁止。除了极少数情况外,在 PyPI 存在的近 15 年里,没有人积极地上传过这些其他类型的文件,因此它们显然没有特别有用。此外,虽然 .tar.xz
从理论上讲比其他 .tar.*
格式更好,因为它通过 LZMA 实现了更好的压缩率,但它仅在 Python 3.3 及更高版本中可用,并且对 lzma C 库有可选依赖项。
查看我们确实在当前使用的三种扩展名,也很容易得出结论,.tar.bz2
也可以被禁止。它上传的文件数量很少,并且需要额外的可选 C 库来处理 bzip2 压缩。
最后我们讨论 .tar.gz
和 .zip
。观察这两个格式的纯数字,我们可以看到 .tar.gz
是迄今为止上传最多的格式,总上传量为 444,338 次,而 .zip
只有 58,774 次。在 POSIX 操作系统上,.tar.gz
也是所有当前发布的 Python 和 setuptools 版本的默认生成格式。此外,这两种文件类型都使用相同的 C 库(zlib
),该库也是 bdist_wheel
和 bdist_egg
所必需的。在 .tar.gz
和 .zip
之间做出选择的两个问题是,虽然在 POSIX 操作系统上 .tar.gz
是默认格式,但在 Windows 上 .zip
是默认格式,并且 bdist_wheel
格式也使用 zip。
本 PEP 建议,对于 sdist,我们允许使用 任一 .tar.gz
或 .zip
,而不是尝试将标准化到其中一个。
限制每个版本的 sdist 数量
PyPI 上的 sdist 应该是特定软件版本的一个唯一真实来源。但是,当前 PyPI 允许您为每个允许的 sdist 文件扩展名上传一个 sdist。目前,这允许一个项目大约有 10 个不同的 sdist,但即使有了本 PEP,它也允许单个版本的两个不同的真实来源。拥有多个 sdist 通常会导致一些奇怪的 bug,这些 bug 仅在用户使用哪个 sdist 时才会暴露出来。
为了解决这个问题,本 PEP 建议每个项目的每个版本只允许一个 sdist。
移除流程
本 PEP 不建议从 PyPI 中删除任何现有文件,仅不允许上传新的文件。此限制将分阶段在每个项目的基础上实施,以便项目能够在适用的情况下适应新的限制。
首先,任何现有项目都将被标记为允许上传旧文件类型,而没有此标记的任何项目(即新项目)将无法上传除扩展名为 .tar.gz
或 .zip
的 sdist
、bdist_wheel
和 bdist_egg
之外的任何内容。然后,任何从未上传过需要旧文件类型标记的文件的现有项目都将删除该标记,也使其受新限制的约束。最后,将向所有仍然保留旧文件类型标记的项目的维护者发送一封电子邮件,通知他们即将实施的上传新限制,并告知他们这些限制将在 1 个月后开始应用于他们项目的未来上传。最后,1 个月后,所有项目都将删除旧文件类型标记,并且 PyPI 上将不再支持上传此类文件。
此计划应该不会造成太大的干扰,因为它不会删除任何现有文件,并且它阻止上传的文件类型要么不是特别有用(或使用)的文件类型,要么它们可以通过稍微更改其流程来继续上传类似类型的文件。
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0527.rst