PEP 425 – 构建发行版的兼容性标签
- 作者:
- Daniel Holth <dholth at gmail.com>
- BDFL代表:
- Alyssa Coghlan <ncoghlan at gmail.com>
- 状态:
- 最终
- 类型:
- 标准跟踪
- 主题:
- 打包
- 创建:
- 2012年7月27日
- Python版本:
- 3.4
- 历史记录:
- 2012年8月8日,2012年10月18日,2013年2月15日
- 决议:
- Python-Dev邮件
摘要
本PEP指定了一个标签系统,用于指示构建或二进制发行版与哪些版本的Python兼容。一组三个标签指示构建发行版需要哪个Python实现和语言版本、ABI和平台。这些标签非常简洁,因为它们将包含在文件名中。
PEP接受
此PEP于2013年2月17日由Alyssa Coghlan接受。
基本原理
如今,“python setup.py bdist”在PyPy和CPython上生成相同的文件名,但生成不兼容的归档文件,这使得在同一个文件夹或索引中共享构建的发行版变得不方便。相反,构建的发行版应该具有包含足够信息的文件命名约定,以便确定特定归档文件是否与特定实现兼容。
之前的尝试来自CPython是唯一重要实现并且ABI与Python语言版本相同的时候。本规范通过将Python实现、语言版本、ABI和平台作为一组标签来改进旧方案。
通过将它支持的标签与发行版列出的标签进行比较,安装程序可以做出明智的决定,即是否下载特定构建的发行版,而无需读取其完整元数据。
概述
标签格式为{python标签}-{abi标签}-{平台标签}
- python标签
- ‘py27’,‘cp33’
- abi标签
- ‘cp32dmu’,‘none’
- 平台标签
- ‘linux_x86_64’,‘any’
例如,标签py27-none-any表示与Python 2.7(任何Python 2.7实现)兼容,没有任何abi要求,在任何平台上。
使用
构建的wheel
包格式在其文件名中包含这些标签,格式为{distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl
。其他包格式可能具有自己的约定。
细节
Python标签
Python标签指示发行版所需的实现和版本。主要实现有缩写代码,最初
- py:通用Python(不需要特定于实现的功能)
- cp:CPython
- ip:IronPython
- pp:PyPy
- jy:Jython
其他Python实现应该使用sys.implementation.name
。
版本为py_version_nodot
。CPython可以不用点,但如果需要,则使用下划线_
代替。PyPy可能应该在这里使用自己的版本pp18
,pp19
。
版本可以仅为主要版本2
或3
py2
,py3
,用于许多纯Python发行版。
重要的是,仅限主要版本的标签,如py2
和py3
,不是py20
和py30
的简写。相反,这些标签意味着打包程序有意发布了跨版本兼容的发行版。
单源Python 2/3兼容发行版可以使用复合标签py2.py3
。请参阅下面的Compressed Tag Sets
。
ABI标签
ABI标签指示任何包含的扩展模块所需的Python ABI。对于特定于实现的ABI,实现以与Python标签相同的方式缩写,例如cp33d
将是具有调试功能的CPython 3.3 ABI。
CPython稳定ABI为abi3
,如共享库后缀所示。
具有非常不稳定ABI的实现可以使用其源代码修订版本和编译器标志等的SHA-256哈希的前6个字节(作为8个base64编码字符),但可能不太需要分发二进制发行版。每个实现的社区可以决定如何最好地使用ABI标签。
平台标签
平台标签只是distutils.util.get_platform()
,其中所有连字符-
和句点.
都替换为下划线_
。
- win32
- linux_i386
- linux_x86_64
使用
安装程序使用这些标签来决定从潜在构建发行版的列表中下载哪个构建发行版(如果有)。安装程序维护一个(pyver, abi, arch)元组列表,它将支持这些元组。如果构建发行版的标签in
列表中,则可以安装它。
建议安装程序默认情况下尝试选择最完整功能的构建发行版(最适合安装环境的构建发行版),然后再回退到为旧版Python发布的纯Python版本。还建议安装程序提供一种配置和重新排序允许的兼容性标签列表的方法;例如,用户可能只接受*-none-any
标签,以仅下载将自己宣传为纯Python的构建包。
另一个理想的安装程序功能可能是包含“如果可能,从源代码重新编译”作为比一些兼容但旧的预构建选项更优选的功能。
此示例列表适用于在linux_x86_64系统上运行的CPython 3.3安装程序。它按从最优选(为当前版本的Python构建的发行版,其中包含编译的扩展模块)到最不优选(使用旧版本的Python构建的纯Python发行版)的顺序排列
- cp33-cp33m-linux_x86_64
- cp33-abi3-linux_x86_64
- cp3-abi3-linux_x86_64
- cp33-none-linux_x86_64*
- cp3-none-linux_x86_64*
- py33-none-linux_x86_64*
- py3-none-linux_x86_64*
- cp33-none-any
- cp3-none-any
- py33-none-any
- py3-none-any
- py32-none-any
- py31-none-any
- py30-none-any
- 构建的发行版可能由于除C扩展之外的其他原因而特定于平台,例如通过包含作为子进程调用的本地可执行文件。
有时,特定版本的包将有多个受支持的构建发行版。例如,打包程序可以发布一个标记为cp33-abi3-linux_x86_64
的包,其中包含一个可选的C扩展,以及标记为py3-none-any
的相同发行版,但不包含C扩展。受支持标签列表中标签的索引打破了关联,并且优先安装包含C扩展的包,因为该标签在列表中首先出现。
压缩标签集
为了允许bdist的文件名更紧凑,这些文件名可以与多个兼容性标签三元组一起使用,文件名中的每个标签都可以是“.”分隔的、已排序的标签集。例如,pip是一个纯Python包,它被编写为使用相同的源代码在Python 2和3下运行,它可以分发一个带有标签py2.py3-none-any
的bdist。完整的基本标签列表为
for x in pytag.split('.'):
for y in abitag.split('.'):
for z in archtag.split('.'):
yield '-'.join((x, y, z))
实现此方案的bdist格式应在特定于bdist的元数据中包含扩展标签。此压缩方案可以生成大量不受支持的标签和“不可能”的标签,这些标签不受任何Python实现支持,例如“cp33-cp31u-win64”,因此请谨慎使用。
常见问题
- 默认情况下使用哪些标签?
- 工具应默认使用最优选的体系结构相关标签,例如
cp33-cp33m-win32
或最优选的纯python标签,例如py33-none-any
。如果打包程序覆盖了默认值,则表示他们打算提供跨Python兼容性。 - 如果我的发行版使用了最新版Python独有的功能,我应该使用哪个标签?
- 兼容性标签帮助安装程序选择发行版的单个版本的最兼容构建。例如,当没有
beaglevote-1.2.0
的Python 3.3兼容构建时(它使用Python 3.4独有的功能),它可能仍然使用py3-none-any
标签而不是py34-none-any
标签。Python 3.3用户必须结合其他限定符,例如对旧版本beaglevote-1.1.0
的要求(该版本不使用新功能),才能获得兼容的构建。 - 为什么Python版本号中没有
.
? - CPython已经持续了20多年,没有3位数的主版本发布。这种情况应该还会持续一段时间。其他实现可以使用_作为分隔符,因为-和.都分隔了周围的文件名。
- 为什么将连字符和其他非字母数字字符规范化为下划线?
- 为了避免与分隔文件名组件的“.”和“-”字符冲突,并为了与更广泛的文件名文件系统限制(包括在不加引号的情况下用于URL路径)更好地兼容。
- 为什么不使用特殊字符<X>而不是“.”或“-”?
- 要么是因为该字符在某些上下文中不方便或可能令人困惑(例如,“+”必须在URL中加引号,“~”在POSIX中用于表示用户的家目录),要么是因为这些优势不足以令人信服地证明更改PEP 427中定义的wheel格式的现有参考实现(例如,在压缩标签中使用“,”而不是“.”来分隔组件)。
- 谁将维护缩写实现的注册表?
- 可以在python-dev邮件列表中请求新的两位字母缩写。根据经验,缩写保留给当前4个最突出的实现。
- 兼容性标签是否放入METADATA或PKG-INFO中?
- 不。兼容性标签是构建发行版元数据的一部分。METADATA/PKG-INFO应该对整个发行版有效,而不是对该发行版的单个构建有效。
- 为什么你没有提到我最喜欢的 Python 实现?
- 缩写的标签方便在公共索引中共享编译后的 Python 代码。你的 Python 实现也可以使用此规范,但需要使用更长的标签。请记住,所有“纯 Python”构建的发行版都只使用“py”。
- 为什么 ABI 标签(第二个标签)在参考实现中有时是“none”?
- 由于 Python 2 没有简单的方法获取 SOABI(这个概念来自较新版本的 Python 3),因此在编写本文时,参考实现猜测为“none”。理想情况下,它会检测到类似于较新版本 Python 的“py27(d|m|u)”,但在目前,“none”是一个足够好的方法来表示“不知道”。
参考文献
[1] 文件名嵌入元数据 (http://peak.telecommunity.com/DevCenter/EggFormats#filename-embedded-metadata)
[2] 创建构建发行版 (https://docs.pythonlang.cn/3.4/distutils/builtdist.html)
致谢
作者感谢 Paul Moore、Alyssa Coghlan、Marc Abramowitz 和 Michele Lacchia 先生提供的宝贵帮助和建议。
版权
本文档已进入公有领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0425.rst
上次修改时间:2023-10-11 12:05:51 GMT