Heim  >  Artikel  >  Backend-Entwicklung  >  Verschiedene Möglichkeiten, zirkuläre Importe in Python zu beheben

Verschiedene Möglichkeiten, zirkuläre Importe in Python zu beheben

Linda Hamilton
Linda HamiltonOriginal
2024-11-05 02:21:01787Durchsuche

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.

Beispiel für einen zirkulären Import

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.

Korrigieren Sie zirkuläre Importe in Python

Verschieben Sie Code in eine gemeinsame Datei

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.

Verschieben Sie den Import an das Ende des Moduls

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

Modul innerhalb des Klassen-/Funktionsbereichs importieren

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.

Verwenden des Modulnamens/Alias

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()

Verwendung der Importlib-Bibliothek

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

Zirkuläre Importe in Python-Paketen

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.

Different Ways to Fix Circular Imports in Python

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.

Different Ways to Fix Circular Imports in Python

So sieht der Importzyklus jetzt aus.

Different Ways to Fix Circular Imports in Python

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.

Abschluss

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn