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ån Python.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 av PY_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 till 3. Detta fungerar på samma sätt som 0x03020000 (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: