C API-stabilitet¶
Om inte annat dokumenterats omfattas Pythons C API av policyn för bakåtkompatibilitet, PEP 387. De flesta ändringar av det är källkompatibla (vanligtvis genom att bara lägga till nytt API). Att ändra befintligt API eller ta bort API görs endast efter en föråldringsperiod eller för att åtgärda allvarliga problem.
CPythons Application Binary Interface (ABI) är framåt- och bakåtkompatibelt över en mindre utgåva (om dessa kompileras på samma sätt; se Överväganden om plattform nedan). Så kod kompilerad för Python 3.10.0 kommer att fungera på 3.10.8 och vice versa, men måste kompileras separat för 3.9.x och 3.11.x.
Det finns två nivåer av C API med olika stabilitetsförväntningar:
Unstable API, kan ändras i mindre versioner utan en utfasningsperiod. Det markeras med prefixet
PyUnstable
i namn.Limited API, är kompatibel med flera mindre utgåvor. När
Py_LIMITED_API
är definierat, exponeras endast denna delmängd frånPython.h
.
Dessa diskuteras mer i detalj nedan.
Namn som föregås av en understrykning, till exempel _Py_InternalState
, är privata API som kan ändras utan föregående meddelande även i patchversioner. Om du behöver använda detta API bör du överväga att kontakta CPython-utvecklare för att diskutera att lägga till offentligt API för ditt användningsfall.
Instabilt C API¶
Alla API som namnges med prefixet PyUnstable
exponerar CPython-implementeringsdetaljer och kan ändras i varje mindre utgåva (t.ex. från 3.9 till 3.10) utan några varningar om föråldring. Den kommer dock inte att ändras i en buggfixversion (t.ex. från 3.10.0 till 3.10.1).
Det är i allmänhet avsett för specialiserade lågnivåverktyg som t.ex. debuggar.
Projekt som använder detta API förväntas följa CPython-utvecklingen och lägga ner extra arbete på att anpassa sig till förändringar.
Binärt gränssnitt för stabila applikationer¶
För enkelhetens skull talar vi i det här dokumentet om tillägg, men Limited API och Stable ABI fungerar på samma sätt för alla användningar av API:et - till exempel inbäddning av Python.
Begränsad C API¶
I Python 3.2 introducerades Limited API, en delmängd av Pythons C API. Tillägg som bara använder Limited API kan kompileras en gång och laddas på flera versioner av Python. Innehållet i det begränsade API:et är listat nedan.
-
Py_LIMITED_API¶
Definiera detta makro innan du inkluderar
Python.h
för att välja att endast använda det begränsade API:et och för att välja den begränsade API-versionen.Definiera
Py_LIMITED_API
till värdet avPY_VERSION_HEX
som motsvarar den lägsta Python-versionen som ditt tillägg stöder. Tillägget kommer att vara ABI-kompatibelt med alla Python 3-versioner från den angivna och framåt, och kan använda Limited API som introducerats fram till den versionen.I stället för att använda makrot
PY_VERSION_HEX
direkt, hårdkoda en minsta minor-version (t.ex.0x030A0000
för Python 3.10) för stabilitet vid kompilering med framtida Python-versioner.Du kan också definiera
Py_LIMITED_API
till3
. Detta fungerar på samma sätt som0x03020000
(Python 3.2, den version som introducerade Limited API).
Stabil ABI¶
För att möjliggöra detta tillhandahåller Python en Stable ABI: en uppsättning symboler som kommer att förbli ABI-kompatibla i alla Python 3.x-versioner.
Anteckning
Det stabila ABI:t förhindrar ABI-problem, som länkarfel på grund av saknade symboler eller datakorruption på grund av ändringar i strukturlayouter eller funktionssignaturer. Andra ändringar i Python kan dock ändra beteendet hos tillägg. Se Pythons policy för bakåtkompatibilitet (PEP 387) för mer information.
Stable ABI innehåller symboler som exponeras i Limited API, men även andra - till exempel funktioner som är nödvändiga för att stödja äldre versioner av Limited API.
I Windows bör tillägg som använder Stable ABI länkas mot python3.dll
snarare än ett versionsspecifikt bibliotek som python39.dll
.
På vissa plattformar kommer Python att leta efter och ladda delade biblioteksfiler som namnges med taggen abi3
(t.ex. mymodule.abi3.so
). Det kontrolleras inte om sådana tillägg överensstämmer med ett stabilt ABI. Användaren (eller deras paketeringsverktyg) måste se till att t.ex. tillägg som är byggda med 3.10+ Limited API inte installeras för lägre versioner av Python.
Alla funktioner i Stable ABI finns som funktioner i Pythons delade bibliotek, inte enbart som makron. Detta gör dem användbara från språk som inte använder C-preprocessorn.
Begränsad API-omfattning och prestanda¶
Målet med det begränsade API:et är att tillåta allt som är möjligt med det fullständiga C API:et, men möjligen med en prestandaförlust.
Till exempel, medan PyList_GetItem()
är tillgänglig, är dess ”osäkra” makrovariant PyList_GET_ITEM()
inte det. Makrot kan vara snabbare eftersom det kan förlita sig på versionsspecifika implementeringsdetaljer för listobjektet.
Utan Py_LIMITED_API
definierad, är vissa C API-funktioner inlinade eller ersatta av makron. Genom att definiera Py_LIMITED_API
inaktiveras denna inlining, vilket ger stabilitet när Pythons datastrukturer förbättras, men eventuellt försämrad prestanda.
Genom att utelämna definitionen Py_LIMITED_API
är det möjligt att kompilera ett Limited API-tillägg med ett versionsspecifikt ABI. Detta kan förbättra prestanda för den Python-versionen, men kommer att begränsa kompatibiliteten. Kompilering med Py_LIMITED_API
kommer då att ge ett tillägg som kan distribueras där en versionsspecifik inte är tillgänglig - till exempel för förhandsversioner av en kommande Python-version.
Begränsade API-förbehåll¶
Observera att kompilering med Py_LIMITED_API
inte är en fullständig garanti för att koden överensstämmer med Limited API eller Stable ABI. Py_LIMITED_API
omfattar endast definitioner, men ett API omfattar även andra frågor, t.ex. förväntad semantik.
Ett problem som Py_LIMITED_API
inte skyddar mot är att anropa en funktion med argument som är ogiltiga i en lägre Python-version. Tänk till exempel på en funktion som börjar acceptera NULL
som ett argument. I Python 3.9 väljer NULL
nu ett standardbeteende, men i Python 3.8 kommer argumentet att användas direkt, vilket orsakar en NULL
dereference och krasch. Ett liknande argument fungerar för fält i structs.
Ett annat problem är att vissa struct-fält för närvarande inte är dolda när Py_LIMITED_API
definieras, trots att de ingår i Limited API.
Av dessa skäl rekommenderar vi att du testar ett tillägg med alla mindre Python-versioner som det stöder, och helst bygger med den lägsta sådana versionen.
Vi rekommenderar också att du granskar dokumentationen för alla API:er som används för att kontrollera om de uttryckligen är en del av det begränsade API:et. Även med Py_LIMITED_API
definierat exponeras några privata deklarationer av tekniska skäl (eller till och med oavsiktligt, som buggar).
Observera också att Limited API inte nödvändigtvis är stabilt: att kompilera med Py_LIMITED_API
med Python 3.8 innebär att tillägget kommer att köras med Python 3.12, men det kommer inte nödvändigtvis att kompilera med Python 3.12. I synnerhet kan delar av det begränsade API:et vara föråldrade och tas bort, förutsatt att det stabila ABI:t förblir stabilt.
Överväganden om plattform¶
ABI-stabilitet beror inte bara på Python, utan också på den kompilator som används, bibliotek på lägre nivå och kompilatoralternativ. När det gäller Stabil ABI definierar dessa detaljer en ”plattform”. De beror vanligtvis på operativsystemstyp och processorarkitektur
Det är varje enskild Python-distributörs ansvar att se till att alla Python-versioner på en viss plattform är byggda på ett sätt som inte bryter mot Stable ABI. Detta är fallet med Windows- och macOS-utgåvor från python.org
och många tredjepartsdistributörer.
Innehåll i begränsat API¶
För närvarande innehåller Limited API följande artiklar:
PyByteArrayIter_Type
PyBytesIter_Type
PyBytes_DecodeEscape()
PyBytes_Repr()
PyCFunction_GetFlags()
PyCFunction_GetFunction()
PyCFunction_GetSelf()
PyCFunction_Type
PyCapsule_Type
PyClassMethodDescr_Type
PyDictItems_Type
PyDictIterItem_Type
PyDictIterKey_Type
PyDictIterValue_Type
PyDictKeys_Type
PyDictProxy_Type
PyDictRevIterItem_Type
PyDictRevIterKey_Type
PyDictRevIterValue_Type
PyDictValues_Type
PyEnum_Type
PyErr_Display()
PyErr_ProgramText()
PyFilter_Type
PyGILState_STATE
PyGetSetDescr_Type
PyListIter_Type
PyListRevIter_Type
PyLongRangeIter_Type
PyMap_Type
PyMemberDescr_Type
PyMemoryView_Type
PyMethodDescr_Type
PyModuleDef_Base
PyModuleDef_Type
PyOS_InterruptOccurred()
PyOS_mystricmp()
PyOS_mystrnicmp()
PyRangeIter_Type
PyRange_Type
PyReversed_Type
PySetIter_Type
PySuper_Type
PyThread_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_Type
PyTupleIter_Type
PyUnicode_AsDecodedObject()
PyUnicode_AsDecodedUnicode()
PyUnicode_AsEncodedObject()
PyUnicode_AsEncodedUnicode()
PyVarObject.ob_base
PyWeakReference
PyWrapperDescr_Type
PyZip_Type
Py_FileSystemDefaultEncodeErrors
Py_FileSystemDefaultEncoding
Py_GetRecursionLimit()
Py_HasFileSystemDefaultEncoding
Py_MakePendingCalls()
Py_SetRecursionLimit()
Py_UTF8Mode
Py_intptr_t
Py_uintptr_t
ssizessizeargfunc
ssizessizeobjargproc
symtable