The Stable ABI asabi3 can no longer be preserved, and requires replacement.abi2026 will be the first replacement, providing resolution of current knownincompatibilities, with planned retirement after at least 10 years. The next ABI(for example,abi2031) will have at least five years of overlap with thepreceding one.
Long-term stability will be enabled through a mechanism for runtime ABIdiscovery, allowing extensions to be run with earlier releases that support thesame ABI. Changes and additions during the lifespan of an ABI can be added asinterfaces, allowing them to be discovered at runtime so that callers canchoose suitable fallback behaviour. Currently, such additions prevent extensionsfrom loading at all on earlier runtimes.
Theabi3 ABI will be retained in GIL-enabled builds for at least five years,after which time it may be retired (with onlyabi2026 and later beingavailable). It’s possible that GIL-enabled builds will be retired completelybefore then. Free-threaded builds do not haveabi3, and so their firstStable ABI would beabi2026.
This PEP uses “GIL-enabled build” as an antonym to “free-threaded build”,that is, an interpreter or extension built withoutPy_GIL_DISABLED.
The Stable ABI is currently not available for free-threaded builds.Extensions will fail to build whenPy_LIMITED_API is defined.Likewise, extensions built for GIL-enabled builds of CPython will fail to load(or crash) on free-threaded builds.
In itsacceptance postforPEP 779, the Steering Council stated that it “expects that Stable ABIfor free-threading should be prepared and defined for Python 3.15”.
This PEP proposes a Stable ABI that will be compatible with all variants of 3.15and later, allowing package developers to produce a single build of theirextensions.
PEP 803 is an alternative to this proposal, and much of the background textused in this PEP is deliberately identical. We thank the PEP 803 author for theuse of their text.
Python’s Stable ABI, as defined inPEP 384 andPEP 652, provides a way tocompile extension modules that can be loaded on multiple minor versions of theCPython interpreter.Several projects use this to limit the number ofwheels (binary artefacts)that need to be built and distributed for each release, and/or to make iteasier to test with pre-release versions of Python.
With free-threading builds (PEP 703) being on track to eventually becomethe default (PEP 779), we need a way to make the Stable ABI availableto those builds.
To build against the Stable ABI, the extension must use aLimited API,that is, only a subset of the functions, structures, etc. that CPythonexposes.The Limited API is versioned, and building against Limited API 3.Xyields an extension that is ABI-compatible with CPython 3.X andany laterversion (though bugs in CPython sometimes cause incompatibilities in practice).Also, the Limited API is not “stable”: newer versions may remove API items thatwere available in older versions.
This PEP proposes a significant change to versioning of both the Limited APIand the Stable ABI. The goal is to enable long-term management of stabilityand compatibility, while also allowing users of the limited subsets to haveaccess to innovations in later Python releases.
The design in this PEP makes several assumptions:
Note that much of the specification is identical toPEP 803, and readersshould refer to that proposal for details. The ABI Stability, Build-time Macrosand Interfaces API sections are unique to this proposal.
The Stable ABI will be frozen for a duration of at least 10 years. When a newversion of the Stable ABI is frozen, the existing version will continue to besupported for at least 5 years. This allows ample migration time for packagemaintainers (and other users) to migrate their entire range of supportedreleases simultaneously. However, if the Python core development team sees noreason to replace the current Stable ABI, freezing a new version may bedeferred.
New Stable ABIs are defined using the PEP process, with their name reflectingthe release year of the first runtime that supports it.
When a Stable ABI is frozen, the year becomes the name of the ABI. For example,we anticipate that the first ABI under this scheme will beabi2026, and willbe supported by all releases until at least 2036. If support is dropped in 2036,thenabi2031 would be the migration target, which allows package developersto support at least five years of releases after their own migration.
While frozen, no ABI changes are permitted at all. Additions are not permitted,nor are removals, modifications, or drastic semantic changes. Critically, anextension module compiled against a particular ABI must load successfully(as in, all imported symbols are satisfied on all supported platforms) againstany Python version supporting that ABI, earlier or later.
Semantic changes that cannot be detected at runtime via existing compatible ABIare not permitted. That is, the APIs to detect whether a particular behaviour isexpected on the current Python release must have been available on all earlierreleases that support the ABI.
Version 3.15 of the Limited API will make a number of structures opaque, suchthat users of them cannot make any assumptions about their size or layout. Thedetails may be found inPEP 803, and the proposal here is identical.
Implementation of this PEP requiresPEP 793 (PyModExport:A new entry point for C extension modules) to beaccepted, providing a new “export hook” for defining extension modules.Using the new hook will become mandatory in Limited API 3.15.
This proposal is identical to that ofPEP 803.
SeePEP 803 for details. This proposal is identical.
We requirePy_LIMITED_API to be defined to0x03ff_YYYY - that is,the high word is a constant0x03ff, while the low word is the ABI name(year) as a hexadecimal value. While this results in a decimal value that is notthe same as the year, we consider that to be unimportant as the value is anarbitrary label and more likely to be specified as a constant (in acccommand line) than a calculated value.
The use of0x03ff as the constant is intended to allow compatibility withearlier runtimes. The same constant when used with headers only supportingabi3 will select the “most complete” version of ABI3 available in thatrelease. For example, using0x03ff2026 in 3.15+ would selectabi2026,while in 3.10 will select the version of ABI3 that works for 3.10-3.14.
Wheels should be tagged with the ABI tagabi2026. No changes to Python orplatform tags are needed. It is perhaps worth noting that releases tagged forcp314 or earlier will never be compatible withabi2026, as it was notpresent, and so a wheel taggedpy3-abi2026-<plat> is not going to cause awheel using the new Stable ABI to be loaded by an older release.
Implementing this PEP will make it possible to build extensions thatcan be successfully loaded on free-threaded Python, but not necessarily onesthat are thread-safe without a GIL.
Limited API to allow thread-safety without a GIL – presumablyPyMutex,PyCriticalSection, and similar – will be added via the C API working group,or in a follow-up PEP.
A newinterfaces API will be added to Python and the new Limited API. This APIis to satisfy the “semantic changes are detectable on all releases” requirementfrom the ABI Stability section above. That is, consumers[1] will beable to adopt a new API immediately, compile for the Limited API with the latestrelease, and retain binary compatibility for all releases supporting that ABI.
In short, the primary API isPyObject_GetInterface(), which delegatesto a new native-only type slot to fill in a C struct containing either data orfunction pointers. Because the C struct definition is embedded into theextension, rather than obtained at runtime, an extension module can be aware oflater structs while running against releases of Python that do not provide it.
If the call toPyObject_GetInterface requests a struct that is not availableon the current version, or is not available for the provided object, the callfails safely. The caller may then use fallback logic (for example, usingabstract Python APIs) or abort, based on their preference.
For example, if a new API were to be added duringabi2026’s life that allowsmore efficient access to anint object’s internal data, rather than adding anew API, we would create a new interface: a struct containing a function pointerto copy the data to a new location, and a previously unused index/name for thatinterface. The caller can callPyObject_GetInterface(int_object,&intf_struct)first; if it succeeds, call (a hypothetical)(*intf_struct.copy_bits)(&intf_struct,dest,sizeof(dest)); if it fails,they can usePyObject_CallMethod(int_object,"to_bytes",...) to perform thesame operation, but less efficiently. The final result of this example is asingle extension module that is binary compatible withall releases supportingabi2026 but is more efficient when running against newer releases of Python.
Overview complete, here is the full specification of each new API:
// Abstract API to request an interface for an object (or type).PyAPI_FUNC(int)PyObject_GetInterface(PyObject*obj,void*intf);// API to release an interface.PyAPI_FUNC(int)PyInterface_Release(void*intf);// Expected layout of the start of each interface. Actual interface structs// will add additional function pointers or data.typedefstructPyInterface_Base{// sizeof(self), for additional validation that the caller is passing// the correct structure.Py_ssize_tsize;// Unique identifier for the struct. Details below.uint64_tname;// Function to release the struct (e.g. to decref any PyObject fields).// Should only be invoked by PyInterface_Release(), not directly.int(*release)(structPyInterface_Base*intf);}PyInterface_Base;// Type slot definition for PyTypeObject field.typedefint(*Py_getinterfacefunc)(PyObject*o,PyInterface_Base*intf);
The unique identifier for the struct is a 64-bit integer defined as a macro (toensure that compiled extension modules embed the value, rather than trying todiscover it at runtime). The top 32 bits are the namespace, and implementersdefining their own structs should choose a unique value for themselves. Zerois reserved for CPython.
The interface name is to identify the struct layout, and so any defined objectcan reuse an interface name from another namespace, provided the struct matches.This is intentional, as it allows third-party types to implement the sameinterfaces as core types without having to rely on sharing the implementation.To be clear, an interface defined for CPython may be used by other extensionmodules without changing the name or the name’s namespace.
For example, consider a hypothetical interface to implementPyDict_GetItemString(). The coredict type may do internaloptimizations to locate entries by string key, while an external type can usethe same interface to do their own optimization. To the caller, it appears touse the same interface, and so the caller is compatible with a broader range oftypes than if it were using (for example) CPython’s concrete object APIs.
Interface names cannot be removed from headers at any time, and structuredefinitions can only be removed when all Stable ABI versions supporting them arefully retired. However, objects may stop returning a particular interface if itis no longer recommended or reliable, even if earlier releases did return them.Runtime deprecation warnings may be used if appropriate, no particular rule isspecified.
Interface structures are fixed and cannot be changed. When a change is required,a new interface should be defined with a new name. The fields added to a structfor an interface are public API and should be documented. Fields that are notintended for direct use should begin with an underscore, but otherwise cannot bemade “private”. Interfaces may provide a mix of data and function pointers, oruse strongPyObject* references to avoid race conditions.
After retrieving an interface, the interface must remain valid until it isreleased, even if the reference to the object is freed. The behaviour of theinterface may handle changes to the underlying object however appropriate, butprobably should document its choices. It would not be unreasonable to have twosimilar interfaces that handle these kind of changes differently (e.g. oneinterface that locks the object for the lifetime of the interface, while anotherdoes not).
The process of adding new Limited APIs changes somewhat: rather than having anABI that grows with each release, new APIs may be added as a real function forwhen the Limited API is not in use, but should be added as a static inlinefunction for the Limited API. This static inline function should use aninterface to detect the functionality at runtime, and include an abstractfallback or suitable exception.
This means that consumers can adopt a new API immediately, compile for theLimited API with the latest release, and retain binary compatibility for allreleases that support the same Stable ABI.
At the next Stable ABI freeze, the API can either be promoted to the new StableABI/Limited API as a real function, or retained as an interface.
Limited API 3.15 will not be backwards-compatible with older CPython releases,due to removed structs and functions.
Extension authors who cannot switch may continue to use Limited API 3.14and below for use on the GIL enabled build.
No changes toabi3 will be made to the GIL enabled build, and all existingsymbols will remain available, even though these are no longer available undernew Stable ABIs.
Making free-threaded builds the default/only release for CPython will be abackwards-incompatible change, and extension authors will need to have migrated.
None known.
The native ABI of Python can be described as a periodically updated standard orspecification, identified by year, similar to other languages. Any extensionmodule can use this ABI, and declares which ABI they expect as part of theirdistribution information. Any Python implementation may choose to support aparticular ABI version, and any extension also supporting that version should beusable.
Migrating fromabi3 to a new ABI may involve source code changes, but canbe treated as a one-time task. In many, if not most, cases, source code will becompatible with bothabi3 and the new ABI, simplifying production of buildsfor old releases and current releases. In general,abi3 builds should bebuilt with the oldest supported CPython runtime, and new ABI builds should bebuilt with the latest CPython runtime (or another compatible runtime).
Migrating from one ABI (e.g.abi2026) to the next (e.g.abi2031) shouldbe a manual task. There is enough overlap between ABI updates that most projectsonly need to support one at a time, and can update all of their builds at onceif their own support matrix allows. There is no expectation for packagemaintainers to immediately support each new ABI.
Forward-and-backward compatibility is ensured by dynamic interface detection.Code using recently added limited API functions will run on older releases,though potentially at lower performance. See the documentation for new functionsto find information about any Limited API-specific nuances.
Non-C callers should use the interfaces mechanism directly to get access to newfeatures without artificially limiting their compatibility to newer releases.The names and struct layouts of interfaces are guaranteed stable for all time,though it should not be assumed that an interface will be available for alltime, and suitable fallback code (either an alternative implementation or errorhandling) should be included.
SeePEP 803 for links to reference implementations for the aspects inheritedfrom that PEP.
The reference implementation of interfaces iszooba/cpython#44.
[See discussion for now.]
[See discussion for now.]
This document is placed in the public domain or under theCC0-1.0-Universal license, whichever is more permissive.
Source:https://github.com/python/peps/blob/main/peps/pep-0809.rst
Last modified:2025-10-01 17:55:07 GMT