CEP 20 - 支持 abi3
Python 包
标题 | 支持 abi3 Python 包 |
状态 | 已批准 |
作者 | Isuru Fernando <ifernando@quansight.com> |
创建于 | 2024 年 7 月 1 日 |
更新于 | 2024 年 12 月 19 日 |
讨论 | https://github.com/conda/ceps/pull/86 |
实施 | https://github.com/conda/conda-build/pull/5456 |
摘要
本 CEP 详细说明了 conda 安装工具(conda/mamba/micromamba/pixi)如何支持 abi3
Python 包,以及 conda 构建工具 (conda-build/rattler-build) 如何构建它们。
动机
在为 Python 构建扩展时,它们可能会使用 Python 次版本特定的符号。这导致扩展只能在该次版本上使用。这些扩展通过扩展名后缀来识别。例如,foo.cpython-310-x86_64-linux-gnu.so
是一个仅支持 x86_64-linux-gnu
平台上的 CPython 3.10 的扩展。
然而,某些符号在所有 Python 主版本.次版本中都可用,并且 Python 版本有一定的下限。这些符号是有限 C API 的一部分。保证在 Python 3.X 中引入的有限 C API 中的符号在 Python 3.Y 中可用,对于任何 Y >= X
。仅使用这些符号的扩展通过扩展名后缀 abi3.so
来识别。例如,foo.abi3.so
。
这些扩展仅支持构建它们的平台(例如 x86_64-linux-gnu
),但这并未在扩展名后缀中指定。
请注意,稳定的 ABI 仅特定于 CPython,并且与 PyPy 或其他 Python 实现不兼容。对于独立于 Python 实现的 ABI,请参阅 HPy 项目。
构建 abi3
包的动机是我们只需要为一个 Python 版本构建扩展,并且该扩展将适用于任何后续的 Python 版本。这减少了构建矩阵,从 4-5 个 Python 次版本减少到一个 Python 次版本,并减轻了包构建者的维护负担。
noarch:Python 包
abi3
包与 Python 版本无关,我们将首先查看 noarch: python
包,它们也与 Python 版本无关,并且此外还与架构无关。
noarch: python
包具有以下几个属性
-
A1:它们在
info/index.json
中具有subdir: noarch
。 -
A2:它们在
info/index.json
中具有noarch: python
。 -
A3:Python 文件位于
<PREFIX>/site-packages
中。 -
A4:入口点记录在
info/link.json
中。
conda 安装工具执行四件事来支持它们
-
B1:
<PREFIX>/site-packages
中的文件被移动到正确的位置。例如:<PREFIX>/lib/python3.10/site-packages
。 -
B2:Python 文件(以
*.py
结尾的文件)被编译为.pyc
文件。例如:<PREFIX>/lib/python3.10/site-packages/foo.py
被编译为<PREFIX>/lib/python3.10/site-packages/__pycache__/foo.cpython-310.pyc
。 -
B3:创建的
.pyc
文件记录在<PREFIX>/conda-meta/<pkg>.json
中,以便在卸载包时正确删除它们。 -
B4:
info/link.json
中的入口点被物化。
info/link.json 文件
noarch: python
的 info/link.json
示例看起来像
{
"noarch": {
"entry_points": [
"isympy = isympy:main"
],
"type": "python"
},
"package_metadata_version": 1,
"preferred_env": "foo"
}
noarch: generic
的 info/link.json
示例看起来像
{
"noarch": {
"type": "generic"
},
"package_metadata_version": 1
}
这里 preferred_env
自 2017 年以来被 conda 忽略,并且不受其他 conda 安装工具的支持。因此,info/link.json
专门用于 noarch
包,并且在两种类型中,noarch: generic
包不需要任何特殊操作。
info/index.json 文件
noarch: python
配方示例。
{
"arch": null,
"build": "pyh2585a3b_103",
"build_number": 103,
"depends": [
"mpmath >=0.19",
"python >=3.8"
],
"license": "BSD-3-Clause",
"license_family": "BSD",
"name": "sympy",
"noarch": "python",
"platform": null,
"subdir": "noarch",
"timestamp": 1718625708903,
"version": "1.12.1"
}
求解器工具中的当前行为
Conda 包上传工具(如 anaconda-client
)使用 A1
将包上传到 noarch
子目录。
Conda 安装工具的行为略有不同。
Conda
- 操作
B1、B2、B3
应用于具有A3
的包。 - 操作
B4
应用于具有A4
的包。
Micromamba
- 操作
B1、B2、B3
应用于同时具有A2、A3
的包。 - 操作
B4
应用于同时具有A2、A4
的包。
abi3
包的实现
安装工具中的支持
我们要求 abi3
包中具有以下属性
-
C1:它们具有
subdir: <platform>
,其中<platform>
是构建包的子目录。 -
C2:它们具有
noarch: python
。 -
C3:应用
A2、A3、A4
。
这与当前的 conda/mamba/micromamba
安装工具兼容。
构建工具中的支持
这需要构建工具支持设置 subdir: <platform>
。
特别是,配方作者将设置
build:
python_version_independent: true
requirements:
host:
- python
- python-abi3
这将使构建工具
- D1:在
info/index.json
中设置noarch: python
。
请注意,python-abi3
将设置运行时需求。这是配方作者明确要求的,以便我们不将此 CEP 限制为 abi3
包,并允许 abi4
等的可能性。
一个 python-abi3=3.8
包会在其 run_exports
条目中设置自身,并将具有以下要求
requirements:
run:
- cpython >=3.8
- python-gil
考虑的替代方案
在 post-link.sh
脚本中应用所有操作。
在 python-feedstock 中提供的草案工作。这是 @mbargull 提出的建议,但一些社区成员(@baszalmstra,@wolfv)不喜欢 post-link 脚本,因为它们可以用于任意代码执行。但是,在作者看来,这种攻击媒介并不是一个新的,因为安装工具使用主机环境中的 Python 可执行文件来编译 Python 文件。
带有 __linux, __osx, __win
约束的 noarch: python
包。
@wolfv
的这个建议并不理想,因为它会使 noarch
子目录 repodata.json
文件中充斥着对相关平台无用的包。
新的 package_metadata_version
由于我们可以在当前安装工具的约束范围内工作,因此我们不需要来自安装工具的额外支持。
版权
所有 CEP 均明确采用 CC0 1.0 通用。