Heim > Artikel > Backend-Entwicklung > Verschiedene Möglichkeiten, zirkuläre Importe in Python zu beheben
Sind Sie schon einmal auf zirkuläre Importe in Python gestoßen? Nun, es ist ein sehr häufiger Codegeruch, der darauf hindeutet, dass etwas mit dem Design oder der Struktur nicht stimmt.
Wie erfolgt der zirkuläre Import? Dieser Importfehler tritt normalerweise auf, wenn zwei oder mehr voneinander abhängige Module versuchen zu importieren, bevor sie vollständig initialisiert werden.
Nehmen wir an, wir haben zwei Module: module_1.py und module_2.py.
# module_1.py from module_2 import ModY class ModX: mody_obj = ModY()
# module_2.py from module_1 import ModX class ModY: modx_obj = ModX()
In den obigen Codeausschnitten sind sowohl module_1 als auch module_2 voneinander abhängig.
Die Initialisierung von mody_obj in Modul_1 hängt von Modul_2 ab und die Initialisierung von modx_obj in Modul_2 hängt von Modul_1 ab.
Das nennen wir eine zirkuläre Abhängigkeit. Beide Module bleiben in den Importschleifen hängen, während sie versuchen, sich gegenseitig zu laden.
Wenn wir module_1.py ausführen, erhalten wir den folgenden Traceback.
Traceback (most recent call last): File "module_1.py", line 1, in <module> from module_2 import ModY File "module_2.py", line 1, in <module> from module_1 import ModX File "module_1.py", line 1, in <module> from module_2 import ModY ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)
Dieser Fehler erklärt die Situation des zirkulären Imports. Als das Programm versuchte, ModY aus Modul_2 zu importieren, war Modul_2 zu diesem Zeitpunkt nicht vollständig initialisiert (aufgrund einer anderen Importanweisung, die versucht, ModX aus Modul_1 zu importieren).
Wie behebe ich zirkuläre Importe in Python? Es gibt verschiedene Möglichkeiten, zirkuläre Importe in Python zu beseitigen.
Wir können den Code in eine gemeinsame Datei verschieben, um Importfehler zu vermeiden, und dann versuchen, die Module aus dieser Datei zu importieren.
# main.py ----> common file class ModX: pass class ModY: pass
Im obigen Codeausschnitt haben wir die Klassen ModX und ModY in eine gemeinsame Datei (main.py) verschoben.
# module_1.py from main import ModY class Mod_X: mody_obj = ModY()
# module_2.py from main import ModX class Mod_Y: modx_obj = ModX()
Jetzt importieren module_1 und module_2 die Klassen aus main, wodurch die zirkuläre Importsituation behoben wird.
Bei diesem Ansatz gibt es ein Problem. Manchmal ist die Codebasis so groß, dass es riskant wird, den Code in eine andere Datei zu verschieben.
Wir können die Importanweisung am Ende des Moduls verschieben. Dies gibt Zeit, das Modul vollständig zu initialisieren, bevor ein anderes Modul importiert wird.
# module_1.py class ModX: pass from module_2 import ModY class Mod_X: mody_obj = ModY()
# module_2.py class ModY: pass from module_1 import ModX
Durch den Import von Modulen innerhalb des Klassen- oder Funktionsumfangs können zirkuläre Importe vermieden werden. Dadurch kann das Modul nur importiert werden, wenn die Klasse oder Funktion aufgerufen wird. Dies ist relevant, wenn wir die Speichernutzung minimieren möchten.
# module_1.py class ModX: pass class Mod_X: from module_2 import ModY mody_obj = ModY()
# module_2.py class ModY: pass class Mod_Y: from module_1 import ModX modx_obj = ModX()
Wir haben die Importanweisungen innerhalb der Klassen Mod_X und Mod_Y in Modul_1 bzw. Modul_2 verschoben.
Wenn wir entweder Modul_1 oder Modul_2 ausführen, erhalten wir keinen zirkulären Importfehler. Dieser Ansatz macht die Klasse jedoch nur innerhalb des Klassenbereichs zugänglich, sodass wir den Import nicht global nutzen können.
Die Verwendung des Modulnamens oder einfach eines Alias wie diesem löst das Problem. Dadurch können beide Module vollständig geladen werden, indem die zirkuläre Abhängigkeit bis zur Laufzeit verschoben wird.
# module_1.py from module_2 import ModY class ModX: mody_obj = ModY()
# module_2.py from module_1 import ModX class ModY: modx_obj = ModX()
Wir können auch die Importlib-Bibliothek verwenden, um die Module dynamisch zu importieren.
Traceback (most recent call last): File "module_1.py", line 1, in <module> from module_2 import ModY File "module_2.py", line 1, in <module> from module_1 import ModX File "module_1.py", line 1, in <module> from module_2 import ModY ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)
# main.py ----> common file class ModX: pass class ModY: pass
Normalerweise zirkuläre Importe stammen aus Modulen innerhalb desselben Pakets. Bei komplexen Projekten ist auch die Verzeichnisstruktur komplex, mit Paketen innerhalb von Paketen.
Diese Pakete und Unterpakete enthalten __init__.py-Dateien, um einen einfacheren Zugriff auf Module zu ermöglichen. Hier entstehen manchmal unbeabsichtigt zirkuläre Abhängigkeiten zwischen Modulen.
Wir haben die folgende Verzeichnisstruktur.
# module_1.py from main import ModY class Mod_X: mody_obj = ModY()
Wir haben ein Paket mainpkg und eine main.py-Datei. Wir haben zwei Unterpakete modpkg_x und modpkg_y innerhalb von mainpkg.
So sieht jede Python-Datei in modpkg_x und modpkg_y aus.
mainpkg/modpkg_x/__init__.py
# module_2.py from main import ModX class Mod_Y: modx_obj = ModX()
Diese Datei importiert beide Klassen (ModX und ModA) aus module_1 und module_1_1.
mainpkg/modpkg_x/module_1.py
# module_1.py class ModX: pass from module_2 import ModY class Mod_X: mody_obj = ModY()
Das Modul_1 importiert eine Klasse ModY aus Modul_2.
mainpkg/modpkg_x/module_1_1.py
# module_2.py class ModY: pass from module_1 import ModX
Das Modul_1_1 importiert nichts. Es ist von keinem Modul abhängig.
mainpkg/modpkg_y/__init__.py
# module_1.py class ModX: pass class Mod_X: from module_2 import ModY mody_obj = ModY()
Diese Datei importiert die Klasse ModY aus Modul_2.
mainpkg/modpkg_y/module_2.py
# module_2.py class ModY: pass class Mod_Y: from module_1 import ModX modx_obj = ModX()
Das Modul_2 importiert eine Klasse ModA aus dem Modul_1_1.
Wir haben den folgenden Code in der Datei main.py.
root_dir/main.py
# module_1.py import module_2 as m2 class ModX: def __init__(self): self.mody_obj = m2.ModY()
Die Hauptdatei importiert eine Klasse ModY aus Modul_2. Diese Datei ist abhängig von module_2.
Wenn wir uns den Importzyklus hier vorstellen, würde er wie folgt aussehen, ohne die Dateien __init__.py in modpkg_x und modpkg_y zu ignorieren.
Wir können sehen, dass die Hauptdatei von Modul_2 abhängt, Modul_1 auch von Modul_2 und Modul_2 von Modul_1_1. Es gibt keinen Importzyklus.
Aber Sie wissen, dass Module von ihrer Datei __init__.py abhängig sind, daher wird die Datei __init__.py zuerst initialisiert und Module werden erneut importiert.
So sieht der Importzyklus jetzt aus.
Dadurch war module_1_1 von module_1 abhängig, was eine gefälschte Abhängigkeit darstellt.
Wenn dies der Fall ist, leeren Sie die __init__.py-Dateien der Unterpakete und die Verwendung einer separaten __init__.py-Datei kann helfen, indem Importe auf Paketebene zentralisiert werden.
# module_1.py from module_2 import ModY class ModX: mody_obj = ModY()
In dieser Struktur haben wir ein weiteres Unterpaket subpkg innerhalb von mainpkg hinzugefügt.
mainpkg/subpkg/__init__.py
# module_2.py from module_1 import ModX class ModY: modx_obj = ModX()
Dadurch können interne Module aus einer einzigen Quelle importiert werden, wodurch die Notwendigkeit von Kreuzimporten verringert wird.
Jetzt können wir die Importanweisung in der Datei main.py aktualisieren.
root_dir/main.py
Traceback (most recent call last): File "module_1.py", line 1, in <module> from module_2 import ModY File "module_2.py", line 1, in <module> from module_1 import ModX File "module_1.py", line 1, in <module> from module_2 import ModY ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)
Dies löst das Problem der zirkulären Abhängigkeit zwischen den Modulen innerhalb desselben Pakets.
Zirkuläre Abhängigkeit oder Import in Python ist ein Codegeruch, der auf eine ernsthafte Umstrukturierung und Umgestaltung des Codes hinweist.
Sie können eine der oben genannten Möglichkeiten ausprobieren, um zirkuläre Abhängigkeiten in Python zu vermeiden.
?Andere Artikel, die Sie interessieren könnten, wenn Ihnen dieser gefallen hat
✅Vorlagenvererbung in Flask mit Beispiel.
✅Unterschied zwischen exec() und eval() mit Beispielen.
✅Verstehen der Verwendung globaler Schlüsselwörter in Python.
✅Python-Typhinweise: Funktionen, Rückgabewerte, Variablen.
✅Warum Schrägstrich und Sternchen in der Funktionsdefinition verwendet werden.
✅Wie wirkt sich die Lernrate auf die ML- und DL-Modelle aus?
Das ist alles für den Moment.
Codieren Sie weiter✌✌.
Das obige ist der detaillierte Inhalt vonVerschiedene Möglichkeiten, zirkuläre Importe in Python zu beheben. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!