5. Importsystemet

Python-kod i en module får tillgång till koden i en annan modul genom att importing den. Satsen import är det vanligaste sättet att anropa importmaskineriet, men det är inte det enda sättet. Funktioner som importlib.import_module() och den inbyggda __import__() kan också användas för att anropa importmaskineriet.

Satsen import kombinerar två operationer; den söker efter den namngivna modulen och binder sedan resultatet av denna sökning till ett namn i det lokala omfånget. Sökoperationen i import-satsen definieras som ett anrop till funktionen __import__(), med lämpliga argument. Returvärdet för __import__() används för att utföra namnbindningsoperationen i import-satsen. Se import-satsen för exakta detaljer om denna namnbindningsoperation.

Ett direkt anrop till __import__() utför endast modulsökningen och, om den hittas, skapandet av modulen. Även om vissa sidoeffekter kan uppstå, t.ex. import av överordnade paket och uppdatering av olika cacheminnen (inklusive sys.modules), är det bara import som utför en namnbindningsoperation.

När en import-sats exekveras anropas den inbyggda standardfunktionen __import__(). Andra mekanismer för att anropa importsystemet (t.ex. importlib.import_module()) kan välja att kringgå __import__() och använda sina egna lösningar för att implementera importsemantik.

När en modul importeras första gången söker Python efter modulen och om den hittas skapar den ett modulobjekt [1] och initialiserar det. Om den namngivna modulen inte kan hittas genereras ett ModuleNotFoundError. Python implementerar olika strategier för att söka efter den namngivna modulen när importmaskinen anropas. Dessa strategier kan modifieras och utökas genom att använda olika hooks som beskrivs i avsnitten nedan.

Ändrad i version 3.3: Importsystemet har uppdaterats för att fullt ut implementera den andra fasen av PEP 302. Det finns inte längre något implicit importmaskineri - hela importsystemet är exponerat genom sys.meta_path. Dessutom har stöd för inbyggda namnrymdspaket implementerats (se PEP 420).

5.1. importlib

Modulen importlib tillhandahåller ett omfattande API för att interagera med importsystemet. Till exempel ger importlib.import_module() ett rekommenderat, enklare API än inbyggda __import__() för att anropa importmaskineriet. Se dokumentationen för biblioteket importlib för mer information.

5.2. Paket

Python har bara en typ av modulobjekt, och alla moduler är av denna typ, oavsett om modulen är implementerad i Python, C eller något annat. För att hjälpa till att organisera moduler och tillhandahålla en namngivningshierarki har Python ett koncept av packages.

Du kan tänka på paket som kataloger i ett filsystem och moduler som filer i kataloger, men ta inte den här analogin alltför bokstavligt eftersom paket och moduler inte behöver komma från filsystemet. I den här dokumentationen använder vi den praktiska analogin med kataloger och filer. Precis som kataloger i filsystemet är paket organiserade hierarkiskt, och paket kan i sig innehålla underpaket, liksom vanliga moduler.

Det är viktigt att komma ihåg att alla paket är moduler, men inte alla moduler är paket. Eller uttryckt på ett annat sätt, paket är bara en speciell typ av modul. Specifikt betraktas alla moduler som innehåller ett __path__-attribut som ett paket.

Alla moduler har ett namn. Namn på underpaket separeras från namnet på det överordnade paketet med en punkt, på samma sätt som Pythons standardsyntax för attributåtkomst. Således kan du ha ett paket som heter email, som i sin tur har ett underpaket som heter email.mime och en modul inom det underpaketet som heter email.mime.text.

5.2.1. Vanliga paket

Python definierar två typer av paket, regular packages och namespace packages. Vanliga paket är traditionella paket som de fanns i Python 3.2 och tidigare. Ett vanligt paket implementeras vanligtvis som en katalog som innehåller en fil med namnet __init__.py. När ett reguljärt paket importeras körs filen __init__.py implicit, och de objekt som definieras i den binds till namn i paketets namnrymd. Filen __init__.py kan innehålla samma Python-kod som vilken annan modul som helst, och Python kommer att lägga till några ytterligare attribut till modulen när den importeras.

Följande filsystemlayout definierar t.ex. ett ”föräldrapaket” på högsta nivån med tre underpaket:

förälder/
    __init__.py
    en/
        __init__.py
    två/
        __init__.py
    tre/
        __init__.py

Import av parent.one kommer implicit att exekvera parent/__init__.py och parent/one/__init__.py. Efterföljande import av parent.two eller parent.three kommer att exekvera parent/two/__init__.py respektive parent/three/__init__.py.

5.2.2. Paket för namnrymden

Ett namnrymdspaket är en sammansättning av olika portioner, där varje portion bidrar med ett underpaket till moderpaketet. Delar kan finnas på olika platser i filsystemet. Delar kan också finnas i zip-filer, på nätverket eller någon annanstans som Python söker efter under import. Namnrymdspaket kanske inte direkt motsvarar objekt i filsystemet; de kan vara virtuella moduler som inte har någon konkret representation.

Namnrymdspaket använder inte en vanlig lista för sitt attribut __path__. De använder istället en anpassad iterabel typ som automatiskt utför en ny sökning efter paketdelar vid nästa importförsök inom det paketet om sökvägen till deras överordnade paket (eller sys.path för ett paket på högsta nivån) ändras.

Med namnrymdspaket finns det ingen fil med namnet parent/__init__.py. Det kan faktiskt finnas flera parent-kataloger som hittas under import-sökningen, där var och en tillhandahålls av en annan del. Därför kanske parent/one inte finns fysiskt bredvid parent/two. I det här fallet skapar Python ett namnrymdspaket för det översta parent-paketet när det eller ett av dess underpaket importeras.

Se även PEP 420 för specifikation av namnrymdspaket.

5.3. Söker

För att påbörja sökningen behöver Python fullständigt kvalificerat namn på modulen (eller paketet, men för denna diskussions syfte är skillnaden oväsentlig) som importeras. Detta namn kan komma från olika argument till import-satsen, eller från parametrarna till funktionerna importlib.import_module() eller __import__().

Detta namn kommer att användas i olika faser av importsökningen, och det kan vara den prickade sökvägen till en undermodul, t.ex. foo.bar.baz. I det här fallet försöker Python först importera foo, sedan foo.bar och slutligen foo.bar.baz. Om någon av de mellanliggande importerna misslyckas genereras ett ModuleNotFoundError.

5.3.1. Modulens cache

Den första platsen som kontrolleras under importsökningen är sys.modules. Denna mappning fungerar som en cache för alla moduler som tidigare har importerats, inklusive mellanliggande sökvägar. Så om foo.bar.baz tidigare har importerats, kommer sys.modules att innehålla poster för foo, foo.bar och foo.bar.baz. Varje nyckel kommer att ha motsvarande modulobjekt som sitt värde.

Under importen söks modulnamnet upp i sys.modules och om det finns där är det associerade värdet den modul som uppfyller importkraven och processen avslutas. Men om värdet är None, så uppstår ett ModuleNotFoundError. Om modulnamnet saknas kommer Python att fortsätta att söka efter modulen.

sys.modules är skrivbar. Att radera en nyckel kanske inte förstör den associerade modulen (eftersom andra moduler kan innehålla referenser till den), men det kommer att ogiltigförklara cacheposten för den namngivna modulen, vilket gör att Python måste söka på nytt efter den namngivna modulen vid nästa import. Nyckeln kan också tilldelas None, vilket tvingar nästa import av modulen att resultera i ett ModuleNotFoundError.

Se dock upp, för om du behåller en referens till modulobjektet, ogiltigförklarar dess cache-post i sys.modules och sedan återimporterar den namngivna modulen, kommer de två modulobjekten inte att vara desamma. Däremot kommer importlib.reload() att återanvända samma modulobjekt och helt enkelt återinitialisera modulens innehåll genom att köra om modulens kod.

5.3.2. Sökare och lastare

Om den namngivna modulen inte finns i sys.modules, används Pythons importprotokoll för att hitta och ladda modulen. Detta protokoll består av två konceptuella objekt, finders och loaders. En sökares uppgift är att avgöra om den kan hitta den namngivna modulen med hjälp av någon strategi som den känner till. Objekt som implementerar båda dessa gränssnitt kallas importers - de returnerar sig själva när de upptäcker att de kan ladda den begärda modulen.

Python innehåller ett antal standardsökare och importörer. Den första vet hur man hittar inbyggda moduler, och den andra vet hur man hittar frysta moduler. En tredje standardsökare söker efter moduler i en import path. import path är en lista med platser som kan vara sökvägar till filsystem eller zip-filer. Den kan också utökas till att söka efter alla lokaliserbara resurser, till exempel de som identifieras av webbadresser.

Importmaskineriet är utbyggbart, så nya sökare kan läggas till för att utöka modulens sökmöjligheter.

Sökare laddar faktiskt inte moduler. Om de kan hitta den namngivna modulen returnerar de en module spec, en inkapsling av modulens importrelaterade information, som importmaskineriet sedan använder när modulen laddas.

I följande avsnitt beskrivs protokollet för sökare och laddare mer i detalj, inklusive hur du kan skapa och registrera nya för att utöka importmaskineriet.

Ändrad i version 3.4: I tidigare versioner av Python returnerade sökare laddare direkt, medan de nu returnerar modulspecifikationer som innehåller laddare. Laddare används fortfarande under import men har färre ansvarsområden.

5.3.3. Importera hooks

Importmaskineriet är utformat för att vara utbyggbart; den primära mekanismen för detta är importkrokarna. Det finns två typer av import-hooks: metakrokar och importvägskrokar.

Meta-hooks anropas i början av importbearbetningen, innan någon annan importbearbetning har ägt rum, förutom sys.modules cache look up. Detta gör att meta-hooks kan åsidosätta sys.path-behandling, frysta moduler eller till och med inbyggda moduler. Meta-hooks registreras genom att nya sökobjekt läggs till i sys.meta_path, enligt beskrivningen nedan.

Import sökvägs-hooks anropas som en del av sys.path (eller package.__path__) bearbetning, vid den punkt där deras associerade sökvägsobjekt påträffas. Importsökvägskrokar registreras genom att lägga till nya anropbara filer i sys.path_hooks enligt beskrivningen nedan.

5.3.4. Metasökvägen

När den namngivna modulen inte hittas i sys.modules söker Python vidare i sys.meta_path, som innehåller en lista över metasökvägssökarobjekt. Dessa sökare tillfrågas för att se om de vet hur de ska hantera den namngivna modulen. Metasökvägssökare måste implementera en metod som heter find_spec() som tar tre argument: ett namn, en importsökväg och (eventuellt) en målmodul. Metasökvägssökaren kan använda vilken strategi den vill för att avgöra om den kan hantera den namngivna modulen eller inte.

Om metasökvägssökaren vet hur den ska hantera den namngivna modulen returneras ett spec-objekt. Om den inte kan hantera den namngivna modulen returneras None. Om sys.meta_path-behandlingen når slutet av sin lista utan att returnera en specifikation, uppstår ett ModuleNotFoundError. Alla andra undantag som uppstår sprids helt enkelt uppåt och avbryter importprocessen.

Metoden find_spec() för metasökvägssökare anropas med två eller tre argument. Det första är det fullständigt kvalificerade namnet på den modul som importeras, t.ex. foo.bar.baz. Det andra argumentet är de sökvägsposter som ska användas för sökningen efter modulen. För moduler på högsta nivån är det andra argumentet None, men för undermoduler eller underpaket är det andra argumentet värdet på det överordnade paketets attribut __path__. Om det inte går att komma åt rätt __path__-attribut, uppstår ett ModuleNotFoundError. Det tredje argumentet är ett befintligt modulobjekt som kommer att laddas senare. Importsystemet skickar in en målmodul endast under omladdning.

Metasökvägen kan genomkorsas flera gånger för en enda importbegäran. Till exempel, förutsatt att ingen av de inblandade modulerna redan har cachats, kommer import av foo.bar.baz först att utföra en toppnivåimport, anropa mpf.find_spec("foo", None, None) på varje metasökvägssökare (mpf). När foo har importerats importeras foo.bar genom att metasökvägen genomkorsas en andra gång och mpf.find_spec("foo.bar", foo.__path__, None) anropas. När foo.bar har importerats kommer den sista traverseringen att anropa mpf.find_spec("foo.bar.baz", foo.bar.__path__, None).

Vissa metasökvägssökare stöder endast import på toppnivå. Dessa importörer returnerar alltid None när något annat än None anges som det andra argumentet.

Pythons standard sys.meta_path har tre metasökvägssökare, en som vet hur man importerar inbyggda moduler, en som vet hur man importerar frysta moduler och en som vet hur man importerar moduler från en import path (dvs. den path based finder).

Ändrad i version 3.4: Metoden find_spec() för metasökvägssökare ersatte find_module(), som nu är föråldrad. Även om den kommer att fortsätta att fungera utan förändring, kommer importmaskineriet bara att prova den om sökaren inte implementerar find_spec().

Ändrad i version 3.10: Importsystemets användning av find_module() ger nu upphov till ImportWarning.

Ändrad i version 3.12: find_module() har tagits bort. Använd find_spec() istället.

5.4. Laddar

Om och när en modulspecifikation hittas kommer importmaskineriet att använda den (och den laddare som den innehåller) när modulen laddas. Här är en ungefärlig beskrivning av vad som händer under laddningsdelen av import:

modul = Ingen
if spec.loader is not None and hasattr(spec.loader, 'create_module'):
    # Det antas att 'exec_module' också kommer att definieras i laddaren.
    modul = spec.loader.create_module(spec)
om modulen är None:
    module = ModuleType(spec.name)
# De importrelaterade modulattributen ställs in här:
_init_module_attrs(spec, modul)

om spec.loader är None:
    # stöds inte
    höja ImportError
om spec.origin är None och spec.submodule_search_locations inte är None:
    # namnrymdspaket
    sys.modules[spec.name] = modul
elif not hasattr(spec.loader, 'exec_module'):
    modul = spec.loader.load_module(spec.name)
else:
    sys.modules[spec.name] = modul
    försök:
        spec.loader.exec_module(modul)
    utom BaseException:
        try:
            del sys.moduler[spec.namn]
        except KeyError:
            pass
        höja
returnera sys.moduler[spec.namn]

Notera följande detaljer:

  • Om det finns ett befintligt modulobjekt med det angivna namnet i sys.modules, kommer import redan att ha returnerat det.

  • Modulen kommer att finnas i sys.modules innan laddaren exekverar modulkoden. Detta är viktigt eftersom modulkoden kan (direkt eller indirekt) importera sig själv; genom att lägga till den i sys.modules i förväg förhindras obegränsad rekursion i värsta fall och multipel laddning i bästa fall.

  • Om laddningen misslyckas tas den misslyckade modulen - och endast den misslyckade modulen - bort från sys.modules. Alla moduler som redan finns i sys.modules cache, och alla moduler som laddades framgångsrikt som en bieffekt, måste finnas kvar i cachen. Detta står i kontrast till omlastning där även den misslyckade modulen finns kvar i sys.modules.

  • Efter att modulen har skapats men innan den körs ställer importmaskineriet in de importrelaterade modulattributen (”_init_module_attrs” i pseudokodeexemplet ovan), som sammanfattas i en längre avsnitt.

  • Modulens exekvering är det viktiga ögonblicket i laddningen då modulens namnrymd fylls på. Exekveringen är helt delegerad till laddaren, som får bestämma vad som ska fyllas i och hur.

  • Den modul som skapas under laddningen och skickas till exec_module() kanske inte är den som returneras i slutet av import [2].

Ändrad i version 3.4: Importsystemet har tagit över laddningsfunktionernas ansvar för boilerplate. Dessa utfördes tidigare av metoden importlib.abc.Loader.load_module().

5.4.1. Lastare

Modulladdare tillhandahåller den kritiska funktionen för laddning: modulkörning. Importmaskineriet anropar metoden importlib.abc.Loader.exec_module() med ett enda argument, det modulobjekt som ska köras. Alla värden som returneras från exec_module() ignoreras.

Lastmaskinerna måste uppfylla följande krav:

  • Om modulen är en Python-modul (i motsats till en inbyggd modul eller ett dynamiskt laddat tillägg), ska laddaren exekvera modulens kod i modulens globala namnrymd (module.__dict__).

  • Om laddaren inte kan exekvera modulen bör den ge upphov till ett ImportError, även om alla andra undantag som ges upphov till under exec_module() kommer att spridas.

I många fall kan sökaren och laddaren vara samma objekt; i sådana fall skulle metoden find_spec() bara returnera en spec med laddaren inställd på self.

Modulladdare kan välja att skapa modulobjektet under laddningen genom att implementera en create_module()-metod. Den tar ett argument, modulspecifikationen, och returnerar det nya modulobjektet som ska användas under laddningen. create_module() behöver inte ställa in några attribut på modulobjektet. Om metoden returnerar None kommer importmaskineriet att skapa den nya modulen själv.

Tillagd i version 3.4: Metoden create_module() för laddare.

Ändrad i version 3.4: Metoden load_module() ersattes av exec_module() och importmaskineriet tog på sig allt ansvar för laddningen.

För kompatibilitet med befintliga laddare kommer importmekanismen att använda metoden load_module() i laddarna om den finns och laddaren inte också implementerar exec_module(). Dock har load_module() föråldrats och laddare bör istället implementera exec_module().

Metoden load_module() måste implementera alla de standardfunktioner för laddning som beskrivs ovan, förutom att exekvera modulen. Alla samma begränsningar gäller, med några ytterligare förtydliganden:

  • Om det finns ett befintligt modulobjekt med det angivna namnet i sys.modules, måste laddaren använda den befintliga modulen. (Annars kommer importlib.reload() inte att fungera korrekt.) Om den namngivna modulen inte finns i sys.modules, måste laddaren skapa ett nytt modulobjekt och lägga till det i sys.modules.

  • Modulen måste finnas i sys.modules innan laddaren kör modulkoden, för att förhindra obegränsad rekursion eller multipel laddning.

  • Om laddningen misslyckas måste laddaren ta bort alla moduler som den har infogat i sys.modules, men den måste endast ta bort den eller de moduler som misslyckas, och endast om laddaren själv har laddat modulerna explicit.

Ändrad i version 3.5: En DeprecationWarning tas upp när exec_module() är definierad men create_module() inte är det.

Ändrad i version 3.6: Ett ImportError uppstår när exec_module() är definierad men create_module() inte är det.

Ändrad i version 3.10: Användning av load_module() kommer att ge upphov till ImportWarning.

5.4.2. Undermoduler

När en submodul läser in med hjälp av någon mekanism (t.ex. importlib API:er, import- eller import-from-satser eller inbyggda __import__()) placeras en bindning i den överordnade modulens namnrymd till submodulobjektet. Om paketet spam till exempel har en submodul foo, kommer spam efter import av spam.foo att ha ett attribut foo som är bundet till submodulen. Anta att du har följande katalogstruktur:

spam/
    __init__.py
    foo.py

och spam/__init__.py har följande rad i sig:

from .foo import Foo

sedan körs följande sätter namnbindningar för foo och Foo i spam-modulen:

>>> import spam
>>> spam.foo
<module 'spam.foo' from '/tmp/imports/spam/foo.py'>
>>> spam.Foo
<class 'spam.foo.Foo'>

Med tanke på Pythons välkända namnbindningsregler kan detta verka förvånande, men det är faktiskt en grundläggande funktion i importsystemet. Den oföränderliga hållningen är att om du har sys.modules['spam'] och sys.modules['spam.foo'] (som du skulle göra efter ovanstående import), måste den senare visas som foo-attributet för den förra.

5.4.3. Specifikationer för modul

Importmaskineriet använder en mängd information om varje modul under importen, särskilt före inläsningen. Det mesta av informationen är gemensam för alla moduler. Syftet med en moduls spec är att kapsla in denna importrelaterade information för varje enskild modul.

Genom att använda en specifikation under importen kan information överföras mellan komponenterna i importsystemet, t.ex. mellan den sökare som skapar modulspecifikationen och den laddare som utför den. Viktigast av allt är att det gör det möjligt för importmaskineriet att utföra de standardiserade laddningsoperationerna, medan det utan en modulspecifikation var laddaren som hade det ansvaret.

Modulens specifikation visas som module.__spec__. Att ställa in __spec__ på rätt sätt gäller lika för moduler som initieras under tolkens start. Det enda undantaget är __main__, där __spec__ är satt till None i vissa fall.

Se ModuleSpec för detaljer om innehållet i modulspecifikationen.

Tillagd i version 3.4.

5.4.4. __path__-attribut för moduler

Attributet __path__ bör vara en (eventuellt tom) sekvens av strängar som räknar upp de platser där paketets undermoduler kommer att hittas. Om en modul har attributet __path__ är den per definition en package.

Ett pakets attribut __path__ används vid import av dess underpaket. Inom importmaskineriet fungerar det ungefär på samma sätt som sys.path, dvs. tillhandahåller en lista över platser att söka efter moduler under import. Men __path__ är vanligtvis mycket mer begränsad än sys.path.

Samma regler som används för sys.path gäller också för ett pakets __path__. sys.path_hooks (beskrivs nedan) används när ett pakets __path__ genomkorsas.

Ett pakets fil __init__.py kan ställa in eller ändra paketets attribut __path__, och detta var typiskt det sätt som namespace-paket implementerades på före PEP 420. Med införandet av PEP 420 behöver namnrymdspaket inte längre tillhandahålla __init__.py-filer som endast innehåller manipuleringskod för __path__; importmaskineriet ställer automatiskt in __path__ korrekt för namnrymdspaketet.

5.4.5. Modul reprs

Som standard har alla moduler en användbar repr, men beroende på de attribut som anges ovan och i modulens specifikation kan du mer explicit styra repr för modulobjekt.

Om modulen har en specifikation (__spec__), kommer importmekanismen att försöka generera en repr från den. Om det misslyckas eller om det inte finns någon specifikation kommer importsystemet att skapa en standardrepr med hjälp av all information som finns tillgänglig i modulen. Det kommer att försöka använda module.__name__, module.__file__ och module.__loader__ som indata till repr, med standardvärden för all information som saknas.

Här är de exakta reglerna som används:

  • Om modulen har attributet __spec__ används informationen i specifikationen för att generera repr. Attributen ”name”, ”loader”, ”origin” och ”has_location” konsulteras.

  • Om modulen har ett __file__-attribut används detta som en del av modulens repr.

  • Om modulen inte har någon __file__ men har en __loader__ som inte är None, så används laddarens repr som en del av modulens repr.

  • Annars använder du bara modulens __name__ i repr.

Ändrad i version 3.12: Användning av module_repr(), som har varit föråldrad sedan Python 3.4, togs bort i Python 3.12 och anropas inte längre under upplösningen av en moduls repr.

5.4.6. Inaktivering av cachad bytekod

Innan Python laddar in cachad bytecode från en .pyc-fil kontrollerar det om cachen är uppdaterad med källfilen .py. Som standard gör Python detta genom att lagra källfilens senaste ändringstid och storlek i cachefilen när den skrivs. Vid körning validerar importsystemet sedan cachefilen genom att jämföra den lagrade metadatan i cachefilen med källfilens metadata.

Python stöder även ”hash-baserade” cachefiler, som lagrar en hash av källfilens innehåll istället för dess metadata. Det finns två varianter av hash-baserade .pyc-filer: kontrollerade och okontrollerade. För kontrollerade hash-baserade .pyc-filer validerar Python cachefilen genom att hasha källfilen och jämföra den resulterande hashen med hashen i cachefilen. Om en kontrollerad hash-baserad cachefil visar sig vara ogiltig, genererar Python den på nytt och skriver en ny kontrollerad hash-baserad cachefil. För okontrollerade hash-baserade .pyc-filer antar Python helt enkelt att cachefilen är giltig om den finns. Valideringsbeteendet för hash-baserade .pyc-filer kan åsidosättas med flaggan --check-hash-based-pycs.

Ändrad i version 3.7: Lagt till hash-baserade .pyc-filer. Tidigare stödde Python endast tidsstämpelbaserad ogiltigförklaring av bytecode-cacher.

5.5. Den sökvägsbaserade sökaren

Som tidigare nämnts kommer Python med flera standard metasökvägssökare. En av dessa, som kallas path based finder (PathFinder), söker i en import path, som innehåller en lista med path entries. Varje sökvägspost namnger en plats att söka efter moduler på.

Den sökvägsbaserade sökfunktionen vet inte själv hur den ska importera någonting. Istället går den igenom de enskilda sökvägsposterna och associerar var och en av dem med en sökvägspostsökare som vet hur den ska hantera just den typen av sökväg.

Standarduppsättningen av sökfunktioner för sökvägar implementerar all semantik för att hitta moduler i filsystemet och hanterar speciella filtyper såsom Python-källkod (.py-filer), Python-byte-kod (.pyc-filer) och delade bibliotek (t.ex. .so-filer). När det stöds av modulen zipimport i standardbiblioteket hanterar standardverktygen för sökning av sökvägar även inläsningen av alla dessa filtyper (utom delade bibliotek) från zip-filer.

Sökvägsposter behöver inte vara begränsade till filsystemets platser. De kan hänvisa till webbadresser, databasfrågor eller andra platser som kan anges som en sträng.

Den sökvägsbaserade sökfunktionen tillhandahåller ytterligare hooks och protokoll så att du kan utöka och anpassa typerna av sökbara sökvägsposter. Om du t.ex. vill stödja sökvägsposter som nätverks-URL:er kan du skriva en hook som implementerar HTTP-semantik för att hitta moduler på webben. Denna hook (en anropsbar) skulle returnera en path entry finder som stöder det protokoll som beskrivs nedan, som sedan används för att hämta en laddare för modulen från webben.

Ett varningens ord: både i det här avsnittet och i det föregående används termen sökare, och man skiljer mellan dem genom att använda termerna meta path finder och path entry finder. Dessa två typer av sökare är mycket lika, stöder liknande protokoll och fungerar på liknande sätt under importprocessen, men det är viktigt att komma ihåg att de är subtilt olika. I synnerhet fungerar metasökvägssökare i början av importprocessen, vilket framgår av sys.meta_path-traversieringen.

Däremot är sökvägssökare på sätt och vis en implementeringsdetalj av den sökvägsbaserade sökaren, och om den sökvägsbaserade sökaren skulle tas bort från sys.meta_path skulle faktiskt ingen av sökvägssökarens semantik åberopas.

5.5.1. Sökare för banans ingång

path based finder ansvarar för att hitta och ladda Python-moduler och -paket vars plats anges med en sträng path entry. De flesta sökvägsposter namnger platser i filsystemet, men de behöver inte vara begränsade till detta.

Som en metasökvägssökare implementerar path based finder protokollet find_spec() som beskrivits tidigare, men den exponerar ytterligare hooks som kan användas för att anpassa hur moduler hittas och laddas från import path.

Tre variabler används av path based finder, sys.path, sys.path_hooks och sys.path_importer_cache. Attributen __path__ på paketobjekt används också. Dessa ger ytterligare sätt att anpassa importmaskineriet.

sys.path innehåller en lista med strängar som anger sökplatser för moduler och paket. Den initieras från miljövariabeln PYTHONPATH och olika andra installations- och implementationsspecifika standardvärden. Posterna i sys.path kan namnge kataloger i filsystemet, zip-filer och eventuellt andra ”platser” (se modulen site) som ska sökas efter moduler, till exempel webbadresser eller databasfrågor. Endast strängar bör finnas i sys.path; alla andra datatyper ignoreras.

path based finder är en meta path finder, så importmekanismen börjar sökningen efter import path genom att anropa path based finders metod find_spec() som beskrivits tidigare. När argumentet path till find_spec() anges, kommer det att vara en lista med strängvägar att genomsöka - vanligtvis ett pakets __path__-attribut för en import inom det paketet. Om argumentet path är None, indikerar detta en import på högsta nivå och sys.path används.

Den sökvägsbaserade sökaren itererar över varje post i sökvägen och letar för var och en av dessa efter en lämplig path entry finder (PathEntryFinder) för sökvägsposten. Eftersom detta kan vara en dyr operation (t.ex. kan det finnas stat()-anropskostnader för denna sökning), upprätthåller den sökvägsbaserade sökaren en cache som mappar sökvägsposter till sökvägspostsökare. Den här cachen finns i sys.path_importer_cache (trots namnet lagrar den här cachen faktiskt sökobjekt i stället för att vara begränsad till importer-objekt). På detta sätt behöver den dyra sökningen efter en viss path entry-plats path entry finder bara göras en gång. Det står användarkoden fritt att ta bort cacheposter från sys.path_importer_cache, vilket tvingar den sökvägsbaserade sökaren att utföra sökningen efter sökvägsposter igen.

Om sökvägsposterna inte finns i cachen, går den sökvägsbaserade sökaren igenom alla anropbara objekt i sys.path_hooks. Varje path entry hook i denna lista anropas med ett enda argument, sökvägsposterna som ska sökas. Detta anropbara objekt kan antingen returnera en path entry finder som kan hantera sökvägsposterna, eller så kan det generera ImportError. Ett ImportError används av den sökfunktion som baseras på sökvägar för att signalera att hooken inte kan hitta en path entry finder för den path entry. Undantaget ignoreras och import path -iterationen fortsätter. Hooken bör förvänta sig antingen en sträng eller ett byteobjekt; kodningen av byteobjekt är upp till hooken (det kan t.ex. vara en filsystemkodning, UTF-8 eller något annat), och om hooken inte kan avkoda argumentet bör den generera ImportError.

Om sys.path_hooks iteration slutar med att ingen path entry finder returneras, kommer den sökvägsbaserade sökarens find_spec() metod att lagra None i sys.path_importer_cache (för att ange att det inte finns någon sökare för denna sökvägspost) och returnera None, vilket anger att denna meta path finder inte kunde hitta modulen.

Om en path entry finder returneras av en av path entry hook-anropsobjekten på sys.path_hooks, används följande protokoll för att be sökaren om en modulspecifikation, som sedan används när modulen laddas.

Den aktuella arbetskatalogen - som anges med en tom sträng - hanteras på ett något annorlunda sätt än andra poster i sys.path. För det första, om den aktuella arbetskatalogen inte kan bestämmas eller inte existerar, lagras inget värde i sys.path_importer_cache. För det andra söks värdet för den aktuella arbetskatalogen upp på nytt för varje moduluppslagning. För det tredje kommer den sökväg som används för sys.path_importer_cache och som returneras av importlib.machinery.PathFinder.find_spec() att vara den aktuella arbetskatalogen och inte den tomma strängen.

5.5.2. Protokoll för sökning av sökväg

För att stödja import av moduler och initialiserade paket och även för att bidra med delar till namnrymdspaket måste sökvägssökare implementera metoden find_spec().

find_spec() tar två argument: det fullständigt kvalificerade namnet på den modul som importeras och (valfritt) målmodulen. find_spec() returnerar en fullständigt ifylld specifikation för modulen. Denna specifikation kommer alltid att ha ”loader” inställd (med ett undantag).

För att ange för importmaskinen att specifikationen representerar en namnrymd portion, sätter sökvägssökaren submodule_search_locations till en lista som innehåller portionen.

Ändrad i version 3.4: find_spec() ersatte find_loader() och find_module(), som båda nu är föråldrade, men som kommer att användas om find_spec() inte är definierad.

Äldre sökare för sökvägsposter kan implementera en av dessa två föråldrade metoder istället för find_spec(). Metoderna respekteras fortfarande för bakåtkompatibilitetens skull. Men om find_spec() implementeras på sökvägssökaren ignoreras de äldre metoderna.

find_loader() tar ett argument, det fullständigt kvalificerade namnet på den modul som importeras. find_loader() returnerar en 2-tupel där det första objektet är laddaren och det andra objektet är en namnrymd portion.

För bakåtkompatibilitet med andra implementeringar av importprotokollet stöder många sökprogram för sökvägar också samma traditionella metod find_module() som metasökprogram stöder. Metoderna find_module() i sökprogram för sökvägar anropas dock aldrig med ett path -argument (de förväntas registrera lämplig sökvägsinformation från det första anropet till sökvägs-hooken).

Metoden find_module() på sökvägssökare är avskriven, eftersom den inte tillåter sökvägssökaren att bidra med delar till namnrymdspaket. Om både find_loader() och find_module() finns på en sökvägssökare, kommer importsystemet alltid att anropa find_loader() i stället för find_module().

Ändrad i version 3.10: Anrop till find_module() och find_loader() av importsystemet kommer att ge upphov till ImportWarning.

Ändrad i version 3.12: find_module() och find_loader() har tagits bort.

5.6. Ersättande av standardimportsystemet

Den mest tillförlitliga mekanismen för att ersätta hela importsystemet är att ta bort standardinnehållet i sys.meta_path och ersätta det helt med en anpassad metasökvägs-hook.

Om det är acceptabelt att bara ändra beteendet hos importmeddelanden utan att påverka andra API:er som använder importsystemet, kan det räcka med att ersätta den inbyggda funktionen __import__(). Denna teknik kan också användas på modulnivå för att endast ändra beteendet hos importmeddelanden inom den modulen.

För att selektivt förhindra import av vissa moduler från en hook tidigt i metasökvägen (i stället för att helt inaktivera standardimportsystemet) räcker det att skapa ModuleNotFoundError direkt från find_spec() i stället för att returnera None. Det senare anger att metasökvägssökningen ska fortsätta, medan ett undantag avslutar den omedelbart.

5.7. Paket Relativ import

Relativ import använder ledande prickar. En enda ledande punkt anger en relativ import, med början i det aktuella paketet. Två eller fler ledande punkter anger en relativ import till det aktuella paketets överordnade, en nivå per punkt efter den första. Till exempel, med följande paketlayout:

paket/
    __init__.py
    underpaket1/
        __init__.py
        modulX.py
        modulY.py
    underpaket2/
        __init__.py
        modulZ.py
    modulA.py

I antingen subpackage1/moduleX.py eller subpackage1/__init__.py är följande giltig relativ import:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo

Absolut import kan använda antingen syntaxen import <> eller from <> import <>, men relativ import kan bara använda den andra formen; anledningen till detta är att:

import XXX.YYY.ZZZ

bör exponera XXX.YYY.ZZZ som ett användbart uttryck, men .moduleY är inte ett giltigt uttryck.

5.8. Särskilda överväganden för __main__

Modulen __main__ är ett specialfall i förhållande till Pythons importsystem. Som nämnts elsewhere initialiseras modulen __main__ direkt när tolken startas, ungefär som sys och builtins. Till skillnad från dessa två är den dock inte strikt sett en inbyggd modul. Detta beror på att sättet på vilket __main__ initialiseras beror på flaggor och andra alternativ som tolken startas med.

5.8.1. __main__.__spec__

Beroende på hur __main__ initieras kommer __main__.__spec__ att ställas in på lämpligt sätt eller till None.

När Python startas med -m-alternativet, sätts __spec__ till modulspecifikationen för motsvarande modul eller paket. __spec__ fylls också i när modulen __main__ laddas som en del av exekveringen av en katalog, zipfil eller annan sys.path-post.

I de återstående fallen ställs``__main__.__spec__`` in till None, eftersom den kod som används för att fylla i __main__ inte direkt motsvarar en importerbar modul:

  • interaktiv prompt

  • -c option

  • körs från stdin

  • körs direkt från en käll- eller bytecode-fil

Observera att __main__.__spec__ alltid är None i det sista fallet, även om filen tekniskt sett skulle kunna importeras direkt som en modul istället. Använd -m om giltiga metadata för moduler önskas i __main__.

Observera också att även när __main__ motsvarar en importerbar modul och __main__.__spec__ är inställd i enlighet med detta, betraktas de fortfarande som skilda moduler. Detta beror på att block som skyddas av if __name__ == "__main__": kontroller endast exekveras när modulen används för att fylla på main__ namnrymden, och inte under normal import.

5.9. Referenser

Importmaskineriet har utvecklats avsevärt sedan Pythons tidiga dagar. Den ursprungliga specifikationen för paket är fortfarande tillgänglig att läsa, även om vissa detaljer har ändrats sedan det dokumentet skrevs.

Den ursprungliga specifikationen för sys.meta_path var PEP 302, med senare tillägg i PEP 420.

PEP 420 introducerade namespace packages för Python 3.3. PEP 420 introducerade även protokollet find_loader() som ett alternativ till find_module().

PEP 366 beskriver tillägget av attributet __package__ för explicit relativ import i huvudmoduler.

PEP 328 införde absolut och explicit relativ import och föreslog ursprungligen __name__ för semantiken som PEP 366 så småningom skulle specificera för __package__.

PEP 338 definierar exekverande moduler som skript.

PEP 451 lägger till inkapsling av importstatus per modul i spec-objekt. Det avlastar också de flesta av de standardiserade ansvarsområdena för laddare tillbaka till importmaskineriet. Dessa ändringar gör det möjligt att avskaffa flera API:er i importsystemet och även lägga till nya metoder för sökare och laddare.

Fotnoter