Was kann ich bei “ImportError: Name X kann nicht importiert werden” oder “AttributeError: … (höchstwahrscheinlich aufgrund eines zirkulären Imports)” tun?

Lesezeit: 7 Minuten

Benutzer-Avatar
verkauft

Ich habe einen Code, der auf mehrere Dateien verteilt ist, die dies versuchen import voneinander wie folgt:

main.py:

from entity import Ent

Entity.py:

from physics import Physics
class Ent:
    ...

physik.py:

from entity import Ent
class Physics:
    ...

Ich laufe dann ab main.py und ich bekomme folgenden Fehler:

Traceback (most recent call last):
File "main.py", line 2, in <module>
    from entity import Ent
File ".../entity.py", line 5, in <module>
    from physics import Physics
File ".../physics.py", line 2, in <module>
    from entity import Ent
ImportError: cannot import name Ent

Ich gehe davon aus, dass der Fehler auf den Import zurückzuführen ist entity zweimal – einmal drin main.py und später rein physics.py – aber wie kann ich das Problem umgehen?


Siehe auch Was passiert bei der Verwendung von gegenseitigen oder kreisförmigen (zyklischen) Importen in Python? für einen allgemeinen Überblick darüber, was erlaubt ist und was ein Problem beim WRT-Zirkularimport verursacht. Siehe Warum funktionieren kreisförmige Importe scheinbar weiter oben in der Aufrufliste, lösen dann aber einen ImportError weiter unten aus? für technische Details auf warum und wie das Problem tritt auf.

  • In welcher Verzeichnisstruktur werden sie gespeichert und in welchen Verzeichnissen?

    – Ben

    12. Februar 2012 um 20:56 Uhr

  • Schauen Sie sich diese Antwort zum Schleifenimport in Python an: stackoverflow.com/questions/7199466/…

    – Gregor

    12. Februar 2012 um 20:56 Uhr


  • Im Allgemeinen ist es keine gute Programmierpraxis from <module> import <name>oder from <modlue> import *. Importieren Sie besser unter dem Modulnamensraum, um zu verhindern, dass identisch benannte Referenzen überschrieben werden.

    – Joel Cornett

    12. Februar 2012 um 20:57 Uhr

  • @jsells Sie sollten einfach Ihre Klassen anrufen Entity und Vector Anstatt von Ent und Vect, gibt es keinen Grund, solche Namen zu kürzen. Und ja, verwenden import vector und dann x = vector.Vector(0,0,0).

    Benutzer2032433

    18. April 2013 um 17:00 Uhr


  • Hey @Kevin, da du Java besser kennst, was ist dein Eindruck davon Artikel 2008 wobei sich der erste Satz des Autors darauf bezieht, wie zirkuläre Abhängigkeiten sind “ziemlich gängige Praxis” auf Java?

    – HeyWatchThis

    8. Mai 2014 um 20:52 Uhr


Benutzer-Avatar
Teemu Ikonen

Sie haben zirkulär abhängige Importe. physics.py importiert wird aus entity vor dem Unterricht Ent definiert ist und physics versucht zu importieren entity das wird schon initialisiert. Entfernen Sie die Abhängigkeit von physics aus entity Modul.

  • Es gibt nicht viel, was Sie tun können, als Ihren Code umzugestalten. Wenn Sie nicht auf Physik in der Ent-Konstruktordefinition verweisen, verschieben Sie den Import direkt unter die Ent. Fügen Sie in diesem Fall eine Methode wie setPhysics hinzu, um den Import nach dem Konstruktor zu ermöglichen.

    – Teemu Ikonen

    13. Februar 2012 um 7:22 Uhr

  • @jsells Da Sie “schon lange” mit C++ arbeiten, sollten Sie wissen, dass zwei Klassen NIEMALS voneinander abhängig sein sollten. Dies ist in C++ äußerst wichtig, und selbst wenn es in Python nicht die Nummer eins ist, ist es dennoch eine wirklich gute Idee, diese Regel zu befolgen. Habe niemals zwei Klassen, die sich kennen, niemals. Wenn Sie Hilfe beim Erstellen der Struktur für Ihre Klassen benötigen, posten Sie auch den Rest des Codes. Wie genau (in Bezug auf Code) sind Entity und Physics miteinander verknüpft? Ich bin sicher, es gibt eine Problemumgehung für das, was Sie versuchen zu tun.

    Benutzer2032433

    18. April 2013 um 17:03 Uhr


  • @ user2032433 Das hängt wirklich davon ab, was Sie mit “einander kennen” meinen. Es ist wahr, dass gutes Design normalerweise einen Baum von Abhängigkeiten in eine Richtung produziert, und dies ist normalerweise der beste Ansatz. Aber es gibt Ausnahmen davon. C++-Klassen können durchaus zirkulär aufeinander verweisen. (Obwohl es unmöglich ist, dass sie aus einander bestehen.) Ohne Vorwärtsdeklaration ist dies ein Problem in Python, für das es nicht immer eine C++-Lösung gibt.

    – John McFarlane

    3. Juni 2014 um 19:14 Uhr

  • Die Aussage “Zwei Klassen sollten NIEMALS voneinander abhängig sein” ist Quatsch. Zwei-Wege-Navigation (bidirektional) ist in der Objektorientierung sehr verbreitet. books.google.co.uk/…

    – Martin Spamer

    17. Dezember 2014 um 17:38 Uhr

  • Das State-Entwurfsmuster (zum Beispiel) wird normalerweise mit einer Context-Klasse und einer State-Schnittstelle implementiert. State-Instanzen wird die Context-Instanz übergeben, damit sie setState aufrufen können. Dies erfordert, dass der Staat den Kontext kennt und umgekehrt. Inwiefern ist dieses klassische Konstrukt „schlecht im Code“? Eigentlich ist das genau das Problem, mit dem ich in Python kämpfe, aber nicht musste, als ich State in Java implementierte.

    – Vorzeichen

    1. Dezember 2017 um 20:17 Uhr

Während Sie zirkuläre Abhängigkeiten unbedingt vermeiden sollten, können Sie Importe in Python verschieben.

zum Beispiel:

import SomeModule

def someFunction(arg):
    from some.dependency import DependentClass

dies (zumindest in einigen Fällen) wird den Fehler umgehen.

  • zirkuläre Abhängigkeiten werden am besten umgangen

    – kb

    8. Juli 2016 um 21:27 Uhr

  • Basierend auf pep8 ist das Einfügen von import in die Methode keine gute Praxis

    – Tom Sawyer

    10. Mai 2019 um 17:29 Uhr

  • @TomSawyer Warum?

    – Kröw

    3. November 2019 um 7:41 Uhr

  • @TomSawyer Ich empfehle das nicht, aber es ist eine schnelle Lösung, die Sie aus der Klemme bringen kann

    – brüllen

    11. Mai 2020 um 21:24 Uhr

  • @bharling kannst du das etwas näher erklären? Dies war eine starke Lösung für mich

    – ergangen

    3. Juni um 22:23 Uhr

Benutzer-Avatar
Dünen

Dies ist eine zirkuläre Abhängigkeit. Es kann ohne strukturelle Änderungen am Code gelöst werden. Das Problem tritt auf, weil in vector das verlangst du entity sofort nutzbar gemacht werden und umgekehrt. Der Grund für dieses Problem ist, dass Sie um Zugriff auf den Inhalt des Moduls bitten, bevor es fertig ist – indem Sie from x import y. Dies ist im Wesentlichen dasselbe wie

import x
y = x.y
del x

Python ist in der Lage, zirkuläre Abhängigkeiten zu erkennen und die Endlosschleife von Importen zu verhindern. Im Grunde wird nur ein leerer Platzhalter für das Modul erstellt (dh es hat keinen Inhalt). Sobald die zirkulär abhängigen Module kompiliert sind, aktualisiert es das importierte Modul. Das funktioniert ungefähr so.

a = module() # import a

# rest of module

a.update_contents(real_a)

Damit Python mit zirkulären Abhängigkeiten arbeiten kann, müssen Sie verwenden import x nur Stil.

import x
class cls:
    def __init__(self):
        self.y = x.y

Da Sie sich nicht mehr auf den Inhalt des Moduls auf der obersten Ebene beziehen, kann Python das Modul kompilieren, ohne tatsächlich auf den Inhalt der zirkulären Abhängigkeit zugreifen zu müssen. Mit oberster Ebene meine ich Zeilen, die während der Kompilierung ausgeführt werden, im Gegensatz zu den Inhalten von Funktionen (z. y = x.y). Auch statische oder Klassenvariablen, die auf die Modulinhalte zugreifen, verursachen Probleme.

  • Diese Antwort ist wichtig und eine allgemeinere Lösung für andere. Beachten Sie, dass beim Importieren eines lokalen Submoduls (z import app.foo.bar) müssen Sie ihm einen Namen geben (z import app.foo.bar as bar)

    – Datenprinzessin

    28. Juli 2020 um 21:48 Uhr

In meinem Fall habe ich in einem Jupyter-Notebook gearbeitet, und dies geschah, weil der Import bereits zwischengespeichert wurde, als ich die Klasse/Funktion in meiner Arbeitsdatei definiert hatte.

Ich habe meinen Jupyter-Kernel neu gestartet und der Fehler ist verschwunden.

Es ist sehr wichtig, die Logik klar zu machen. Dieses Problem tritt auf, weil die Referenz zu einer toten Schleife wird.

Wenn Sie die Logik nicht ändern möchten, können Sie die Import-Anweisung, die ImportError verursacht hat, an einer anderen Position der Datei platzieren, beispielsweise am Ende.

a.py

from test.b import b2

def a1():
    print('a1')
    b2()

b.py

from test.a import a1

def b1():
    print('b1')
    a1()

def b2():
    print('b2')

if __name__ == '__main__':
    b1()

Sie erhalten einen Importfehler: ImportError: cannot import name 'a1'

Aber wenn wir die Position von aus test.b ändern, importieren Sie b2 in A wie unten:

a.py

def a1():
    print('a1')
    b2()

from test.b import b2

Und wir können bekommen, was wir wollen:

b1
a1
b2

Benutzer-Avatar
Ankit Patidar

Dies ist eine zirkuläre Abhängigkeit. Wir können dieses Problem lösen, indem wir verwenden importieren Modul oder Klasse oder Funktion, wo wir sie brauchten. Wenn wir diesen Ansatz verwenden, können wir die zirkuläre Abhängigkeit beheben

A.py

from B import b2
def a1():
    print('a1')
    b2()

B.py

def b1():
   from A import a1
   print('b1')
   a1()

def b2():
   print('b2')
if __name__ == '__main__':
   b1() 

Ich habe diesen Fehler auch gerade bekommen, aus einem anderen Grund …

from my_sub_module import my_function

Das Hauptskript hatte Windows-Zeilenenden. my_sub_module hatte UNIX-Zeilenenden. Wenn Sie sie so ändern, dass sie gleich sind, wurde das Problem behoben. Sie müssen auch die gleiche Zeichenkodierung haben.

1130810cookie-checkWas kann ich bei “ImportError: Name X kann nicht importiert werden” oder “AttributeError: … (höchstwahrscheinlich aufgrund eines zirkulären Imports)” tun?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy