Informationen zum Python-Importsystem
Sie können das verstehen, Wenn Sie sich von physischen Dateien entfernen und etwas abstrakter denken, wird die Sichtbarkeit des gesamten Systems, wie z. B. Modulnamen, relative Importe, Initialisierungszeitpunkt und Sichtbarkeit der Namen, verbessert.
Beachten Sie, dass dieser Artikel keine ** Namespace-Pakete [^ 1] ** behandelt (weil ich sie nicht verstehe).
Ich habe die Version 3.8.2 von beiden durchsucht.
Bestätigt für die Arbeit mit Python v3.8.2. Überprüfen Sie den Vorgang als Testfall für Pytest.
pip install pytest
Im Anhang finden Sie Informationen zur Funktionsweise des Pytests.
Eine kurze Zusammenfassung der Attribute:
__name__ |
__path__ |
__package__ |
|
---|---|---|---|
Modul: | Modul名 | Keiner | Name des übergeordneten Pakets |
Paket: | Paket名 | Paketのパス | Paket名 |
Dies ist ein in Programmiersprachen häufig verwendetes Konzept
** Dies ist eine Funktion, mit der Sie "Namen" wie den Variablennamen "x" an verschiedenen Stellen im Programm mit unterschiedlichen Bedeutungen verwenden können, ohne Kollisionsangst zu befürchten. ** ** **
Zum Beispiel sind builtins.open
und os.open
beide Funktionsnamen, aber weil sie zu verschiedenen Namespaces gehören,
Kann als unterschiedlich definiert und verwendet werden.
Das unten beschriebene "Modul" ist diese ** Namespace-Einheit **.
In der Python-Dokumentation befindet sich ein Glossar mit einem "Namespace" -Eintrag: https://docs.python.org/ja/3/glossary.html#term-namespace
Wie in der Übersicht erwähnt, ist ein Modul eine ** Namespace-Einheit, die importiert werden kann **.
Erstens, weil ein Modul eine Einheit des Namespace ist, für die Module m
und n
der Name in m`` x
(= mx
) und der Name in n`` x
(= nx
) Wird unterschieden.
Zweitens wird der gesamte Code weniger bewusst in einem Modul ausgeführt, dh in einem Namespace.
Wenn der Code einen Namen deklariert und definiert, wird er in diesem Namespace registriert.
Unmittelbar nach dem Start des Python-Interpreters wird der Code im ** __ main__
Modul-Namespace ** ausgeführt.
Dies wird häufig verwendet, um festzustellen, ob eine .py-Datei direkt gestartet oder importiert wurde.
Das Modul kann dann importiert werden. Ein Modul importieren bedeutet
--Finden und zwischenspeichern Sie das Modul und --Laden und initialisieren,
Das ist. Das Dokument enthält 2 Schritte. Wenn Sie es jedoch als 3 Schritte betrachten, ist die Verarbeitungseinheit leicht zu verstehen.
Einfach ausgedrückt, indem Sie das Modul m
als import m
importieren
--Suchen Sie nach dem Modul m
in sys.path
und registrieren Sie das Modulobjekt im globalen Cache sys.modules
.
m
laden und initialisieren. Zum Beispiel "m.f" oder "m.C".m
im aktuellen Namespace so, dass er auf das Modul m
zeigt.Starten Sie den Python-Interpreter im interaktiven Modus und checken Sie ihn aus. (Teilweise zur besseren Lesbarkeit geformt)
[.../module-experiments]$ python
Python 3.8.2 (default, Apr 18 2020, 18:08:23)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print(__name__)
__main__
>>> import m
>>> sys.modules['m']
<module 'm' from '.../module-experiments/m.py'>
>>> m
<module 'm' from '.../module-experiments/m.py'>
>>> m.f
<function f at 0x108452b80>
>>> m.C
<class 'm.C'>
Sie können sehen, dass das Modul unmittelbar nach dem Start "main" ist.
Sie können auch sehen, dass Sie durch Importieren von m
auf m
, m.f
und m.C
zugreifen können.
Das importierte Modul wird im lokalen Namespace zwischengespeichert. Daher kann wie bei jedem anderen Namen auf ein in eine Funktion importiertes Modul nicht von anderen Funktionen zugegriffen werden. Da der Cache jedoch global ist, kann auf ihn zugegriffen werden.
Ein Paket ist wie ein Modul, nur dass Sie darin nach Submodulen suchen und diese importieren können. Mithilfe von Paketen können Sie eine hierarchische Struktur von Modulen erstellen.
Der Name des Moduls (oder Pakets) ist dann so etwas wie "a.b.c", getrennt durch Punkte.
Durch Importieren des Moduls a.b.c
mit importieren a.b.c
a
--Importieren Sie das Submodul (Paket) b
( a.b
) in den Namespace des Moduls a
--Importieren Sie das Submodul c
( a.b.c
) in den Namespace des Moduls a.b
Auf diese Weise können Sie mit "a.b.c" auf das Modul "a.b.c" zugreifen.
** Hinweis: Sie können mit c
nicht darauf zugreifen. ** ** **
Diese Regel zeigt auch, dass Pakete und Module auf die gleiche Weise importiert werden können.
Natürlich können Sie nicht sofort nach dem Importieren von "a.b.c" auf "a.d" oder "a.d.e" zugreifen. Wenn Sie hier "a.d.e importieren", ist "a" im Cache vorhanden
--Importieren Sie das Submodul (Paket) d
( a.d
) in den Namespace des Moduls a
Kommt nur vor, also wird an diesen Stellen das Modul initialisiert.
Technisch gesehen ist ein Paket ein Modul mit dem Attribut __path__
.
Dieses Attribut wird bei der Suche nach Unterpaketen verwendet.
Mit anderen Worten, in "import a.b.c",
--Finden und importieren Sie "a" aus "sys.path" --Finden und importieren Sie "a.b" von "a .__ path__" im Namespace des Moduls "a" --Finden und importieren Sie "a.b.c" aus "a.b.__ path__" im Namespace des Moduls "a.b"
Das passiert gerade.
Das Modul, das das Paket enthält, hat das Attribut __name__
.
Bei importierten Modulen ist dieser Wert der vollständig qualifizierte Name des Moduls (z. B. "a.b.c").
Da ein Paket ein Modul ist, kann es mit der import-Anweisung wie ein Modul importiert werden.
import ... as ...
Wenn die import-Anweisung eine "as" -Klausel enthält, ist das importierte Modul selbst an einen Namen gebunden, der kleiner oder gleich "as" ist. Mit "a.b als b importieren" können Sie beispielsweise direkt mit dem Namen "b" auf das Modul "a.b" zugreifen.
Zu diesem Zeitpunkt werden, da das Modul "a" geladen und initialisiert ist, die Informationen über das Modul "a" (und natürlich "a.b") zwischengespeichert. A
ist jedoch nicht an den Namespace gebunden.
>>> import sys
>>> import a.b as b
['/Users/shinsa/git/python-experiments/module-experiments/a']
a
>>> sys.modules['a']
<module 'a' from '/Users/shinsa/git/python-experiments/module-experiments/a/__init__.py'>
>>> sys.modules['a.b']
<module 'a.b' from '/Users/shinsa/git/python-experiments/module-experiments/a/b/__init__.py'>
>>> b
<module 'a.b' from '/Users/shinsa/git/python-experiments/module-experiments/a/b/__init__.py'>
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
Der Modulname kommt unmittelbar nach "Import" und Sie können den definierten Namen an dieser Stelle nicht verwenden. Daher können Sie "import a.b.c" nicht als "import b.c" schreiben, nur weil Sie "import a.b as b" sagen.
from
KlauselDiese Form des Imports ist der Fall von "from a.b import c". c
kann ein Modul, ein Paket oder ein Name sein.
Die folgende Verarbeitung wird durchgeführt.
--Import a.b
. Der Name ist jedoch nicht gebunden.
c
zu binden.
--Wenn c
der in a.b
definierte Name ist, binden Sie a.b.c
an den Namen c
.c
ein Modul oder Paket ist, importieren Sie a.b.c
(aber binden Sie den Namen nicht) und binden Sie a.b.c
an den Namen c
.Wenn die "as" -Klausel angegeben ist, ist sie anstelle der Bindung von "c" im obigen Beispiel an den in der "as" -Klausel angegebenen Namen gebunden.
from ... import *
Wenn der zu importierende Name "*" ist, dh "von M import *", dann im Modul "M"
__all__
angegebene Name, falls definiertSind alle im aktuellen Namespace gebunden.
In der Anweisung "from ... import ..." können Sie relative Paketdarstellungen in der Klausel "from" verwenden. Zum Beispiel im Initialisierungsskript für das Paket "a.b" oder im Skript für das Modul "a.b.c"
von ..
bedeutet von a
,
--von .d
ist von a.d
,Vertreten Sie jeden. Sie können mehr Punkte haben.
PEP 366
Relative Paketberechnungen basierten auf dem Attribut __name__
.
Wenn Sie beispielsweise den Interpreter mit "python -m a.b.c" starten, fungiert "a / b / c.py" als "main" -Modul.
Aus diesem Grund gab es ein Problem, dass beispielsweise "a.b.d" nicht relativ importiert werden konnte.
In neueren Versionen von Python werden relative Importe jetzt basierend auf dem Attribut "package" berechnet, wodurch das oben genannte Problem mit der Anrufzeit (PEP 366) behoben wird. Wenn Sie es jedoch mit python <Pfad> / a / b / c.py
starten, müssen Sie die Attribute manuell festlegen.
Bisher haben wir abstrakt über Module, Pakete und path gesprochen. Mit anderen Worten, ich spreche überhaupt nicht über ein bestimmtes Dateisystem. In neueren Versionen ist das Importsystem von Python zu einem sehr abstrakten und leistungsstarken System geworden.
Standardmäßig arbeitet das Importsystem mit einem Dateisystem. Standardmäßig werden Module durch ".py" -Dateien und Pakete durch Verzeichnisse dargestellt. Die Details sind wie folgt und es ist ersichtlich, dass sie bisher zur abstrakten Datenstruktur passen.
sys.path
wird als Dateipfad angenommen und durchsucht. import m
durchsucht die in sys.path
enthaltenen Verzeichnisse nacheinander und m.py
in einem der Verzeichnisse wird importiert.Umgekehrt kann beispielsweise ein URI-basiertes Importsystem implementiert werden, und der Diensterkennungsmechanismus kann unter Verwendung des Python-Importsystems implementiert werden.
Die Python-Dokumentation ist verwirrend, da die Informationen überall verteilt sind. Es ist immer noch verständlich, wenn Sie dies tun, um doppelte Informationen zu vermeiden. Stattdessen wird jede Information subtil dupliziert, aber verstreut. Darüber hinaus sind einige Informationen veraltet.
Recommended Posts