プラットフォームの互換性タグ#

プラットフォーム相互互換性タグは、特定のプラットフォームと互換であるとビルドツールが配布物に印を付けることができるようにし、インストーラが自身が動作しているシステムと互換であるのはどの配布物であるかを理解できるようにします。

概要#

タグの書式は、 {python tag}-{abi tag}-{platform tag} です。

python タグ

'py27' ・ 'cp33'

abi タグ

'cp33dmu' ・ 'none'

プラットフォームタグ

'linux_x86_64' ・ 'any'

例えば、py27-none-any というタグは、abi に対する要求なしに任意のプラットフォームで Python 2.7 (任意の Python 2.7 実装) との互換性を持つことを意味します。

wheel ビルド済みパッケージのフォーマットは、ファイル名の中にこのようなタグを {distribution}-{version}(-{build tag})?-{python tag}-{abitag}-{platform tag}.whl の形で包含しています。他のパッケージフォーマットにはそれぞれ独自の慣習があるかもしれません。

どのようなタグであれ、その中に潜在的に含まれる空白文字は _ で置換されるべきです。

Python タグ#

Python タグは、配布物が必要とする実装やバージョンを示します。主要な実装には短縮系のコードがあって、当初は:

  • py: 一般的な Python (実装に特有な機能を要求しません)

  • cp: CPython

  • ip: IronPython

  • pp: PyPy

  • jy: Jython

Other Python implementations should use sys.implementation.name.

バージョンは py_version_nodot です。 CPython は no dot にせずに済ませますが、必要な場合には代わりにアンダースコア文字 _ が使用されます。 PyPy は、おそらく、ここに pp18pp19 といったそれ自身のバージョンを使います。

多くの純 Python 配布物では、バージョンは 23py2py3 といったメジャーバージョンだけにしておくことができます。

重要なことは、 py2py3 のような major-version-only タグは py20py30 の短縮形であるわけではないということです。そうではなくて、これらのタグは、パッケージ作成者がいくつものバージョンに互換性を持つ配布物を意図的にリリースしたのです。

単一ソースで Python 2/3 に互換性を持つ配布物は、合成タグ py2.py3 を用いることができます。 後述の タグの圧縮された組み合わせ を参照してください。

ABI タグ#

ABI タグは、いずれかの拡張モジュールによってどのような Python ABI が要求されているのかを示します。実装依存の ABI 群については、実装 (の名前) は、たとえば cp33d がデバッグオプション付きの CPython 3.3 ABI のことを指すように、 Python タグと同様のやり方で短縮したものを使います。

CPython の安定版 ABI のことは、共有ライブラリの拡張子と同様に abi3 と書きます。

非常に不安定な ABI を持つ実装は、そのソースコードのリビジョンやコンパイラフラグその他の SHA-256 ハッシュ値の最初の6バイトを (BASE64にエンコードされた8文字として) 用いても構いませんが、おそらくはバイナリ配布物を配布することには大きな需要はないでしょう。それぞれの実装のコミュニティで ABI タグをどのように用いるのが最適かを決定すればよいでしょう。

プラットフォームタグ#

Basic platform tags#

In its simplest form, the platform tag is sysconfig.get_platform() with all hyphens - and periods . replaced with underscore _. Until the removal of distutils in Python 3.12, this was distutils.util.get_platform(). For example:

  • win32

  • linux_i386

  • linux_x86_64

manylinux#

The simple scheme above is insufficient for public distribution of wheel files to Linux platforms, due to the large ecosystem of Linux platforms and subtle differences between them.

Instead, for those platforms, the manylinux standard represents a common subset of Linux platforms, and allows building wheels tagged with the manylinux platform tag which can be used across most common Linux distributions.

The current standard is the future-proof manylinux_x_y standard. It defines tags of the form manylinux_x_y_arch, where x and y are glibc major and minor versions supported (e.g. manylinux_2_24_xxx should work on any distro using glibc 2.24+), and arch is the architecture, matching the value of sysconfig.get_platform() on the system as in the "simple" form above.

The following older tags are still supported for backward compatibility:

  • manylinux1 supports glibc 2.5 on x86_64 and i686 architectures.

  • manylinux2010 supports glibc 2.12 on x86_64 and i686.

  • manylinux2014 supports glibc 2.17 on x86_64, i686, aarch64, armv7l, ppc64, ppc64le, and s390x.

一般に、古めのバージョンの仕様向けにビルドされた配布物には前方互換性があります (というのは、 manylinux1 の配布物はより新しいシステムでも同様に動作するはずだということです) が、後方互換性はありません (manylinux2010 の配布物が 2010 年よりも前に存在していたプラットフォームで動作するとは想定されていないということです) 。

manylinux1manylinux2010 は既に end-of-life に達していて、提供されているビルド環境にはもはやセキュリティアップデートが提供されることはないであろうという警告されていることもあって、パッケージ保守者は最も互換性のある仕様をターゲットにするように努力するべきです。

適切なプロジェクトがサポートするさまざまな manylinux 標準の最低限のバージョンを次に掲げる表に示します:

ツール

manylinux1

manylinux2010

manylinux2014

manylinux_x_y

pip

>=8.1.0

>=19.0

>=19.3

>=20.3

auditwheel

>=1.0.0

>=2.0.0

>=3.0.0

>=3.3.0 [1]

musllinux#

The musllinux family of tags is similar to manylinux, but for Linux platforms that use the musl libc rather than glibc (a prime example being Alpine Linux). The schema is musllinux_x_y_arch, supporting musl x.y and higher on the architecture arch.

The musl version values can be obtained by executing the musl libc shared library the Python interpreter is currently running on, and parsing the output:

import re
import subprocess

def get_musl_major_minor(so: str) -> tuple[int, int] | None:
    """Detect musl runtime version.

    Returns a two-tuple ``(major, minor)`` that indicates musl
    library's version, or ``None`` if the given libc .so does not
    output expected information.

    The libc library should output something like this to stderr::

        musl libc (x86_64)
        Version 1.2.2
        Dynamic Program Loader
    """
    proc = subprocess.run([so], stderr=subprocess.PIPE, text=True)
    lines = (line.strip() for line in proc.stderr.splitlines())
    lines = [line for line in lines if line]
    if len(lines) < 2 or lines[0][:4] != "musl":
        return None
    match = re.match(r"Version (\d+)\.(\d+)", lines[1])
    if match:
        return (int(match.group(1)), int(match.group(2)))
    return None

There are currently two possible ways to find the musl library’s location that a Python interpreter is running on, either with the system ldd command, or by parsing the PT_INTERP section’s value from the executable’s ELF header.

使い方#

タグ類は、 (もしダウンロードが必要なら) 選択可能なビルド済配布物のリストの中からどれをダウンロードするのかをインストーラが決定するために使われます。インストーラは、自身がサポートする (pyver, abi, arch) タプルのリストを維持管理しています。ビルド済配布物のタグがリストに含まれて (in ) いれば、それをインストールすることができます。

古い Python リリース向けに発行された純 Python のバージョンにフォールバックするよりも前に、利用できる中で最も機能を網羅したビルド済配布物 (インストールする先の環境に最も適したもの) をインストーラがデフォルトで選択することが推奨されています。インストーラは、また、受け入れ可能な互換性タグのリストを設定変更したり順序を入れ替えたりする方法を持つことが推奨されています; 例えば、ユーザは、純 Python であると広報しているビルド済みパッケージだけをダウンロードするために、 *-none-any タグだけを受容しても構いません。

互換性はあるがもはや古くなってしまったビルド済みのものを使う選択肢よりもより好ましいという点で、インストーラに望まれるもうひとつの機能は "可能ならソースコードから再コンパイルする" でしょう。

この事例集は、インストーラを linux_x86_64 システム上の CPython 3.3 のもとで走らせるためのものです。最も好ましいもの (最新版の Python 向けにビルドされたコンパイル済みの拡張モジュールが付属している配布物) から、最も好ましくはないもの (古いバージョンの Python でビルドされた純 Python の配布物) へ、という順序で並んでいます:

  1. cp33-cp33m-linux_x86_64

  2. cp33-abi3-linux_x86_64

  3. cp3-abi3-linux_x86_64

  4. cp33-none-linux_x86_64*

  5. cp3-none-linux_x86_64*

  6. py33-none-linux_x86_64*

  7. py3-none-linux_x86_64*

  8. cp33-none-any

  9. cp3-none-any

  10. py33-none-any

  11. py3-none-any

  12. py32-none-any

  13. py31-none-any

  14. py30-none-any

  • ビルド済み配布物は、サブプロセスとして起動されるネーティブの実行可能ファイルを含んでいるなどのようなC 言語拡張以外の理由によって、特定のプラットフォーム向けであっても構いません。

時々、あるパッケージの特定のバージョンとして複数のビルド済み配布物が存在することがあるでしょう。例えば、パッケージ製作者が、 cp33-abi3-linux_x86_64 というタグを付けて追加的な C 言語拡張を含むパッケージをリリースし、そのようなものを含まない同じ配布物に py3-none-any というタグを付けてリリースするような場合です。(このような場合でも) サポートされるタグのリストで先に出現する方を優先するという理由によって C 言語拡張付きのパッケージがそうでないパッケージよりも選好されてインストールされるという形で、インデックスによってどちらかに決めることができます。

圧縮されたタグのセット#

bdists のコンパクトなファイル名で、互換性のあるタグトリプルが複数ある場合にもきちんと動作するものを許容するためには、代わりにファイル名の中のそれぞれのタグが '.' で分割可能でありソート可能であるような一連のタグになっていることが可能です。例えば、 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 に特有のメタデータの中に含んでいるべきです。この圧縮スキームは、サポートされていないタグや例えば "cp33-cp31u-win64" のようにいかなる Python 実装においてもサポートされていない "不可能な" タグを大量に生成すると思われるので、控えめに使うようにしてください。

FAQ#

デフォルトではどんなタグが使われますか?

ツール類は、 cp33-cp33m-win32 のようなアーキテクチャへの依存を示すタグや py33-none-any のような純 Python タグの中で最も好ましいものをデフォルトで採用するべきです。パッケージ製作者がデフォルトをオーバーライドしていたとすれば、それは彼らが異なる Python 間での互換性を提供しようという意図があったことを示しています。

自分の配布物が最新版の Python と相容れない機能を使っているとしたら、どんなタグを使いますか?

互換性タグは、インストーラがある配布物の 単一のバージョン最も互換性がある ビルドを選択する際に助けとなります。例えば、 (Python 3.4 に特有の機能を使っている) beaglevote-1.2.0``には Python 3.3 と互換性を持つビルドがひとつもないという場合でも、 ``py34-none-any タグの代わりに py3-none-any タグを使っても構いません。 Python 3.3 のユーザが互換性のあるビルドを得るためには、新しい機能を使う前のリリースである beaglevote-1.1.0 用の要求 (requirement) などを他の指定子を組み合わせなければなりません。

Python のバージョン番号に . がないのはなぜですか?

CPython は、数字3個のメジャーリリースなしで 20 年以上にわたって存続してきました。これはしばらくの間は続くに違いありません。 - や . が周辺のファイル名を区切る役割を果たしているので、他の実装では _ を区切り子として使っても構いません。

ハイフンやその他の英数字以外の文字をアンダースコアに正規化するのはなぜですか?

ファイル名の部分部分を区分けする . 文字や - 文字との干渉を避けるために、かつ、 (クォートすることなく URL パス内で使用可能であることを含む) 数多あるファイルシステムのファイル名に対する制限事項との間のより良い互換性のために。

何故、 .- の代わりに特殊な文字 <X> を使わないのですか?

それは、その文字が不便であるかコンテクストによっては潜在的に混乱を招きやすい (例えば + は URL 内ではクォートしなければなりませんし、 ~ は POSIX でユーザのホームディレクトリを示すために使われます) から、あるいは、 PEP 427 で定義された wheel フォーマットを参照して作成された既存の参照実装を変更すること (例えば、圧縮タグで部分部分を分割するのに . ではなく , を使うようにすること) を正当化するに足りるだけのアドバンテージがないから、のいずれかです。

誰が実装に関する短縮形のレジストリの維持管理をしているのですか?

python-dev メーリングリストで要求することで、新しい2文字省略形の割り当てを受けることができるでしょう。経験上は、その時点で最も卓越した4個の実装のために省略形が予約されています。

互換性タグは METADATA に含まれるのか、あるいは PKG-INFO か?

否。互換性タグはビルド済み配布物のメタデータの一部です。METADATA / PKG-INFO は、その配布物の単一のビルドではなく配布物の全体にとって正当なものであるべきです。

どうして私のお気に入りの Python 実装について言及しなかったの?

省略形タグは、コンパイル済みの Python コードを公開のインデックスでシェアすることを促進します。あなたの Python 実装においてもこの仕様を使うことができますが、しかしもっと長いタグになってしまうことでしょう。すべての "純 Python" なビルド済み配布物が単に py を使うだけであることを思い出してください。

どうして参照実装における ABI タグ (第2のタグ) は時々 "none" なのですか?

Python 2 では SOABI (より新しい版の Python 3 から来た概念) を作成する簡単な方法がないので、本稿執筆時点の参照実装は "none" なのです。理想的には、それはもっと新しい版の Python に相似の "py27(d|m|u)" を検出するようになるでしょうが、それまでの間は "知られていない" ことを示すのに "none" とすることが必要十分な方法なのです。

歴史#

  • February 2013: The original version of this specification was approved through PEP 425.

  • January 2016: The manylinux1 tag was approved through PEP 513.

  • April 2018: The manylinux2010 tag was approved through PEP 571.

  • July 2019: The manylinux2014 tag was approved through PEP 599.

  • November 2019: The manylinux_x_y perennial tag was approved through PEP 600.

  • April 2021: The musllinux_x_y tag was approved through PEP 656.