C API Stabilität¶
Sofern nicht anders dokumentiert, unterliegt die C-API von Python der Rückwärtskompatibilitätsrichtlinie, PEP 387. Die meisten Änderungen daran sind quelltextkompatibel (typischerweise durch Hinzufügen neuer APIs). Änderungen oder das Entfernen bestehender APIs erfolgen nur nach einer Depikationsperiode oder zur Behebung schwerwiegender Probleme.
Die Application Binary Interface (ABI) von CPython ist über eine Nebenversion hinweg vorwärts- und rückwärtskompatibel (sofern diese auf die gleiche Weise kompiliert wurden; siehe Plattformüberlegungen unten). Code, der für Python 3.10.0 kompiliert wurde, funktioniert also auf 3.10.8 und umgekehrt, muss aber separat für 3.9.x und 3.11.x kompiliert werden.
Es gibt zwei Stufen von C-APIs mit unterschiedlichen Stabilitätsanforderungen
Instabile API, die sich ohne Depikationsperiode in Nebenversionen ändern kann. Sie wird durch das Präfix
PyUnstablein den Namen gekennzeichnet.Eingeschränkte API, die über mehrere Nebenversionen hinweg kompatibel ist. Wenn
Py_LIMITED_APIdefiniert ist, wird nur diese Teilmenge ausPython.hverfügbar gemacht.
Diese werden nachstehend detaillierter besprochen.
Namen, die mit einem Unterstrich beginnen, wie z. B. _Py_InternalState, sind private APIs, die sich ohne Vorankündigung auch in Patch-Releases ändern können. Wenn Sie diese API verwenden müssen, sollten Sie sich mit den CPython-Entwicklern in Verbindung setzen, um die Aufnahme einer öffentlichen API für Ihren Anwendungsfall zu besprechen.
Instabile C API¶
Jede API, die mit dem Präfix PyUnstable benannt ist, offenbart Implementierungsdetails von CPython und kann sich in jeder Nebenversion (z. B. von 3.9 auf 3.10) ohne Depikationswarnungen ändern. Sie wird sich jedoch nicht in einem Bugfix-Release (z. B. von 3.10.0 auf 3.10.1) ändern.
Sie ist im Allgemeinen für spezialisierte, Low-Level-Tools wie Debugger vorgesehen.
Projekte, die diese API verwenden, werden gebeten, die CPython-Entwicklung zu verfolgen und zusätzlichen Aufwand zu betreiben, um sich an Änderungen anzupassen.
Stabile Application Binary Interface¶
Der Einfachheit halber spricht dieses Dokument von *Erweiterungen*, aber die Limited API und die Stable ABI funktionieren für alle Verwendungen der API auf die gleiche Weise – zum Beispiel beim Einbetten von Python.
Eingeschränkte C API¶
Python 3.2 führte die *Limited API* ein, eine Teilmenge der C-API von Python. Erweiterungen, die nur die Limited API verwenden, können einmal kompiliert und auf mehreren Python-Versionen geladen werden. Der Inhalt der Limited API ist weiter unten aufgeführt.
-
Py_LIMITED_API¶
Definieren Sie dieses Makro vor dem Einbinden von
Python.h, um die Limited API zu verwenden und die Version der Limited API auszuwählen.Definieren Sie
Py_LIMITED_APImit dem Wert vonPY_VERSION_HEX, der der niedrigsten Python-Version entspricht, die Ihre Erweiterung unterstützt. Die Erweiterung ist ABI-kompatibel mit allen Python 3-Releases ab der angegebenen Version und kann Limited APIs bis zu dieser Version nutzen.Anstatt das Makro
PY_VERSION_HEXdirekt zu verwenden, sollten Sie für Stabilität bei der Kompilierung mit zukünftigen Python-Versionen eine minimale Nebenversion hartkodieren (z. B.0x030A0000für Python 3.10).Sie können
Py_LIMITED_APIauch auf3definieren. Dies funktioniert genauso wie0x03020000(Python 3.2, die Version, die die Limited API eingeführt hat).
Stabile ABI¶
Um dies zu ermöglichen, bietet Python eine *Stable ABI*: eine Reihe von Symbolen, die über Python 3.x-Versionen hinweg ABI-kompatibel bleiben.
Hinweis
Die Stable ABI verhindert ABI-Probleme wie Linker-Fehler aufgrund fehlender Symbole oder Datenkorruption aufgrund von Änderungen in Struktur-Layouts oder Funktionssignaturen. Andere Änderungen in Python können jedoch das *Verhalten* von Erweiterungen ändern. Details finden Sie in der Kompatibilitätsrichtlinie von Python (PEP 387).
Die Stable ABI enthält Symbole, die in der Limited API verfügbar sind, aber auch andere – zum Beispiel Funktionen, die zur Unterstützung älterer Versionen der Limited API erforderlich sind.
Unter Windows sollten Erweiterungen, die die Stable ABI verwenden, gegen python3.dll verlinkt werden und nicht gegen eine versionsspezifische Bibliothek wie python39.dll.
Auf einigen Plattformen sucht Python nach und lädt gemeinsam genutzte Bibliotheksdateien mit dem Tag abi3 (z. B. mymodule.abi3.so). Es prüft nicht, ob solche Erweiterungen mit einer Stable ABI konform sind. Der Benutzer (oder seine Paketwerkzeuge) muss sicherstellen, dass z. B. mit der Limited API ab 3.10+ erstellte Erweiterungen nicht für niedrigere Python-Versionen installiert werden.
Alle Funktionen in der Stable ABI sind als Funktionen in der gemeinsam genutzten Bibliothek von Python vorhanden, nicht ausschließlich als Makros. Dies macht sie in Sprachen nutzbar, die den C-Präprozessor nicht verwenden.
Eingeschränkter API-Bereich und Leistung¶
Das Ziel der Limited API ist es, alles zu ermöglichen, was mit der vollständigen C-API möglich ist, aber möglicherweise mit Leistungseinbußen.
Zum Beispiel ist PyList_GetItem() verfügbar, aber seine "unsichere" Makrovariante PyList_GET_ITEM() nicht. Das Makro kann schneller sein, da es auf versionsspezifische Implementierungsdetails des Listenobjekts zurückgreifen kann.
Ohne definierte Py_LIMITED_API sind einige C-API-Funktionen Inline-Funktionen oder durch Makros ersetzt. Das Definieren von Py_LIMITED_API deaktiviert dieses Inlining und ermöglicht Stabilität, während die Datenstrukturen von Python verbessert werden, aber möglicherweise die Leistung reduziert wird.
Durch das Weglassen der Py_LIMITED_API-Definition ist es möglich, eine Limited API-Erweiterung mit einer versionsspezifischen ABI zu kompilieren. Dies kann die Leistung für diese Python-Version verbessern, schränkt jedoch die Kompatibilität ein. Die Kompilierung mit Py_LIMITED_API ergibt dann eine Erweiterung, die dort verteilt werden kann, wo eine versionsspezifische nicht verfügbar ist – zum Beispiel für Vorabversionen einer kommenden Python-Version.
Einschränkungen der eingeschränkten API¶
Beachten Sie, dass die Kompilierung mit Py_LIMITED_API *keine* vollständige Garantie dafür ist, dass der Code mit der Limited API oder der Stable ABI konform ist. Py_LIMITED_API deckt nur Definitionen ab, aber eine API umfasst auch andere Probleme, wie erwartete Semantik.
Ein Problem, das Py_LIMITED_API nicht abdeckt, ist das Aufrufen einer Funktion mit Argumenten, die in einer niedrigeren Python-Version ungültig sind. Betrachten Sie zum Beispiel eine Funktion, die jetzt NULL für ein Argument akzeptiert. In Python 3.9 wählt NULL nun ein Standardverhalten, aber in Python 3.8 wird das Argument direkt verwendet, was zu einer NULL-Dereferenzierung und einem Absturz führt. Ein ähnliches Argument funktioniert für Felder von Strukturen.
Ein weiteres Problem ist, dass einige Strukturfelder derzeit nicht ausgeblendet werden, wenn Py_LIMITED_API definiert ist, obwohl sie Teil der Limited API sind.
Aus diesen Gründen empfehlen wir, eine Erweiterung mit *allen* Nebenversionen von Python zu testen, die sie unterstützt, und sie vorzugsweise mit der *niedrigsten* unterstützten Version zu kompilieren.
Wir empfehlen außerdem, die Dokumentation aller verwendeten APIs zu überprüfen, um festzustellen, ob sie explizit Teil der Limited API sind. Selbst mit definierter Py_LIMITED_API werden aus technischen Gründen (oder sogar unbeabsichtigt als Fehler) einige private Deklarationen verfügbar gemacht.
Beachten Sie auch, dass die Limited API nicht unbedingt stabil ist: die Kompilierung mit Py_LIMITED_API mit Python 3.8 bedeutet, dass die Erweiterung mit Python 3.12 ausgeführt wird, aber sie wird nicht unbedingt mit Python 3.12 *kompiliert*. Insbesondere Teile der Limited API können als veraltet markiert und entfernt werden, vorausgesetzt, die Stable ABI bleibt stabil.
Plattformüberlegungen¶
Die ABI-Stabilität hängt nicht nur von Python ab, sondern auch vom verwendeten Compiler, von Low-Level-Bibliotheken und von Compiler-Optionen. Für die Zwecke der Stable ABI definieren diese Details eine "Plattform". Sie hängen normalerweise vom Betriebssystemtyp und der Prozessorarchitektur ab.
Es liegt in der Verantwortung jedes einzelnen Python-Distributors, sicherzustellen, dass alle Python-Versionen auf einer bestimmten Plattform so erstellt werden, dass die Stable ABI nicht beeinträchtigt wird. Dies ist bei Windows- und macOS-Versionen von python.org und vielen Drittanbietern der Fall.
Inhalt der Limited API¶
Derzeit umfasst die Limited API die folgenden Elemente
PyByteArrayIter_TypePyBytesIter_TypePyBytes_DecodeEscape()PyBytes_Repr()PyCFunction_GetFlags()PyCFunction_GetFunction()PyCFunction_GetSelf()PyCFunction_TypePyCapsule_TypePyClassMethodDescr_TypePyDictItems_TypePyDictIterItem_TypePyDictIterKey_TypePyDictIterValue_TypePyDictKeys_TypePyDictProxy_TypePyDictRevIterItem_TypePyDictRevIterKey_TypePyDictRevIterValue_TypePyDictValues_TypePyEnum_TypePyErr_Display()PyErr_ProgramText()PyFilter_TypePyGetSetDescr_TypePyListIter_TypePyListRevIter_TypePyLongRangeIter_TypePyMap_TypePyMemberDescr_TypePyMemoryView_TypePyMethodDescr_TypePyModuleDef_BasePyModuleDef_TypePyOS_InterruptOccurred()PyOS_mystricmp()PyOS_mystrnicmp()PyRangeIter_TypePyRange_TypePyReversed_TypePySetIter_TypePySuper_TypePyThread_GetInfo()PyThread_acquire_lock()PyThread_acquire_lock_timed()PyThread_allocate_lock()PyThread_exit_thread()PyThread_free_lock()PyThread_get_stacksize()PyThread_get_thread_ident()PyThread_get_thread_native_id()PyThread_init_thread()PyThread_release_lock()PyThread_set_stacksize()PyThread_start_new_thread()PyTraceBack_Here()PyTraceBack_Print()PyTraceBack_TypePyTupleIter_TypePyUnicode_AsDecodedObject()PyUnicode_AsDecodedUnicode()PyUnicode_AsEncodedObject()PyUnicode_AsEncodedUnicode()PyVarObject.ob_basePyWeakReferencePyWrapperDescr_TypePyZip_TypePy_FileSystemDefaultEncodeErrorsPy_FileSystemDefaultEncodingPy_GetRecursionLimit()Py_HasFileSystemDefaultEncodingPy_MakePendingCalls()Py_SetRecursionLimit()Py_UTF8ModePy_intptr_tPy_uintptr_tssizessizeargfuncssizessizeobjargprocsymtable