ImportError: Name X kann nicht importiert werden

540

Ich habe vier verschiedene Dateien mit dem Namen: Haupt, Vektor, Entität und Physik. Ich werde nicht den gesamten Code veröffentlichen, sondern nur die Importe, da ich denke, dass dort der Fehler liegt. (Wenn du willst, kann ich mehr posten)

Main:

import time
from entity import Ent
from vector import Vect
#the rest just creates an entity and prints the result of movement

Entität:

from vector import Vect
from physics import Physics
class Ent:
    #holds vector information and id
def tick(self, dt):
    #this is where physics changes the velocity and position vectors

Vektor:

from math import *
class Vect:
    #holds i, j, k, and does vector math

Physik:

from entity import Ent
class Physics:
    #physics class gets an entity and does physics calculations on it.

Ich starte dann von main.py und erhalte die folgende Fehlermeldung:

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 bin sehr neu in Python, habe aber lange mit C ++ gearbeitet. Ich vermute, dass der Fehler auf das zweimalige Importieren einer Entität zurückzuführen ist, einmal in der Haupt- und später in der Physik, aber ich kenne keine Problemumgehung. Kann jemand helfen?

jsells
quelle
Wie ist die Verzeichnisstruktur, in der sie gespeichert sind und in welchen Verzeichnissen?
Ben
1
Schauen Sie sich diese Antwort für den Schleifenimport in Python an: stackoverflow.com/questions/7199466/…
Gregor
Im Allgemeinen ist es keine gute Codierungspraxis from <module> import <name>, oder from <modlue> import *. Besser unter dem Modul-Namespace importieren, um zu verhindern, dass identisch benannte Referenzen überschrieben werden.
Joel Cornett
1
@jsells Sie sollten einfach Ihre Klassen aufrufen Entityund Vectoranstelle von Entund Vectgibt es keinen Grund, solche Namen zu kürzen. Und ja, benutze import vectorund dann x = vector.Vector(0,0,0).
7
Hey @ Kevin, da Sie Java besser kennen, wie ist Ihr Eindruck von diesem Artikel aus dem Jahr 2008, in dem der erste Satz des Autors darauf verweist, wie zirkuläre Abhängigkeiten in Java "ziemlich üblich" sind ?
HeyWatchThis

Antworten:

502

Sie haben zirkularabhängige Importe. physics.pywird importiert, entitybevor die Klasse Entdefiniert wurde, und physicsversucht zu importieren entity, was bereits initialisiert wird. Entfernen Sie die Abhängigkeit physicsvom entityModul.

Teemu Ikonen
quelle
5
Sie können nicht viel tun, als Ihren Code umzugestalten. Wenn Sie in der Ent-Konstruktordefinition nicht auf Physik verweisen, verschieben Sie mport direkt unter Ent. Wenn Sie dies tun, fügen Sie eine Methode wie setPhysics hinzu, um den Import nach dem Konstruktor zu aktivieren.
Teemu Ikonen
12
@jsells Da Sie "lange" mit C ++ gearbeitet haben, sollten Sie wissen, dass zwei Klassen NIEMALS voneinander abhängig sein sollten. Dies ist in C ++ äußerst wichtig, und auch wenn es in Python nicht die Nummer 1 ist, ist es dennoch eine gute Idee, diese Regel zu befolgen. Niemals zwei Klassen haben, die sich kennen. Wenn Sie Hilfe beim Erstellen der Struktur für Ihre Klassen benötigen, veröffentlichen Sie auch den Rest des Codes. Wie genau (in Bezug auf Code) sind Entityund Physicsmiteinander verbunden? Ich bin sicher, es gibt eine Problemumgehung für das, was Sie versuchen zu tun.
7
@ user2032433 Das hängt wirklich davon ab, was du mit "einander kennen" meinst. Es ist richtig, dass gutes Design normalerweise einen Baum von Einwegabhängigkeiten erzeugt, und dies ist normalerweise der beste Ansatz. Es gibt jedoch Ausnahmen. C ++ - Klassen können sich sicherlich zirkulär aufeinander beziehen. (Obwohl es unmöglich ist, dass sie sich zusammensetzen.) Ohne Vorwärtsdeklaration ist dies ein Problem in Python, das nicht immer eine C ++ - Lösung hat.
John McFarlane
93
Die Aussage "zwei Klassen sollten NIEMALS voneinander abhängig sein" ist Müll. Die bidirektionale (bidirektionale) Navigation ist in der Objektorientierung sehr verbreitet. books.google.co.uk/…
Martin Spamer
5
Das Zustandsentwurfsmuster (zum Beispiel) wird normalerweise mit einer Kontextklasse und einer Zustandsschnittstelle implementiert. Instanzen des Status werden die Kontextinstanz übergeben, damit sie setState aufrufen können. Dies setzt voraus, dass der Staat über den Kontext Bescheid weiß und umgekehrt. Wie ist dieses klassische Konstrukt "schlecht im Code"? Eigentlich ist das genau das Problem, mit dem ich in Python ringe, das ich aber nicht musste, als ich State in Java implementierte.
Auspice
141

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

zum Beispiel:

import SomeModule

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

Dies umgeht (zumindest in einigen Fällen) den Fehler.

bharling
quelle
38
zirkuläre Abhängigkeiten werden am besten umgangen
ckb
4
Basierend auf pep8 ist es keine gute Praxis, den Import in die Methode zu setzen
TomSawyer
@ TomSawyer Warum?
Kröw
@ TomSawyer Ich empfehle dies nicht, aber es ist eine schnelle Lösung, die Sie aus einer Bindung
herausholen
117

Dies ist eine zirkuläre Abhängigkeit. Es kann ohne strukturelle Änderungen am Code gelöst werden. Das Problem tritt auf, weil vectorSie verlangen, dass es entitysofort zur Verfügung gestellt wird, und umgekehrt. Der Grund für dieses Problem ist, dass Sie nach dem Zugriff auf den Inhalt des Moduls fragen, bevor es bereit ist - mithilfe von from x import y. Dies ist im Wesentlichen das gleiche 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 Wesentlichen wird lediglich ein leerer Platzhalter für das Modul erstellt (dh es enthält keinen Inhalt). Sobald die zirkular abhängigen Module kompiliert sind, wird das importierte Modul aktualisiert. Das funktioniert so ähnlich.

a = module() # import a

# rest of module

a.update_contents(real_a)

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

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 zum Inhalt von Funktionen (z. B. y = x.y). Statische oder Klassenvariablen, die auf den Modulinhalt zugreifen, verursachen ebenfalls Probleme.

Dünen
quelle
24

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 die andere Position der Datei setzen, z. B. an das 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 folgt:

a.py.

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

from test.b import b2

Und das können wir bekommen, was wir wollen:

b1
a1
b2
g10guang
quelle
18

Dies ist eine zirkuläre Abhängigkeit. Wir können dieses Problem lösen, indem wir das Importmodul oder die Klasse oder Funktion dort verwenden, wo wir es benötigen. 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() 
a.patidar
quelle
17

Ich habe diesen Fehler auch aus einem anderen Grund erhalten ...

from my_sub_module import my_function

Das Hauptskript hatte Windows-Zeilenenden. my_sub_modulehatte UNIX-Zeilenenden. Das Problem wurde behoben, indem das gleiche geändert wurde. Sie müssen auch die gleiche Zeichenkodierung haben.

Marengaz
quelle
7

Wie bereits erwähnt, wird dies durch eine zirkuläre Abhängigkeit verursacht . Was wurde nicht erwähnt ist , dass , wenn Sie Python verwenden Eingabe - Modul und eine Klasse importieren nur annotate verwendet werden Typen , die Sie verwenden können Weiterleiten Referenzen :

Wenn ein Typhinweis Namen enthält, die noch nicht definiert wurden, kann diese Definition als Zeichenfolgenliteral ausgedrückt werden, um später aufgelöst zu werden.

und entfernen Sie die Abhängigkeit (den Import ), z. B. anstelle von

from my_module import Tree

def func(arg: Tree):
    # code

tun:

def func(arg: 'Tree'):
    # code

(Beachten Sie die entfernte importAussage)

Tomasz Bartkowiak
quelle
6

Benennen Sie Ihr aktuelles Python-Skript nicht mit dem Namen eines anderen Moduls, das Sie importieren

Lösung: Benennen Sie Ihr funktionierendes Python-Skript um

Beispiel:

  1. Sie arbeiten in medicaltorch.py
  2. In diesem Skript haben Sie: from medicaltorch import datasets as mt_datasetsWo medicaltorchsoll ein installiertes Modul sein?

Dies wird mit dem fehlschlagen ImportError. Benennen Sie einfach Ihr funktionierendes Python-Skript in 1 um.

Paul
quelle
Danke, das löst das Problem, das ich hatte. Ich habe die colorama-Bibliothek verwendet und die Datei colorama.py benannt, sodass Python nicht wusste, was importiert werden soll. Das Ändern des Dateinamens hilft.
Marek Bodziony
5

Sehen Sie diese hier noch nicht - das ist unglaublich dumm, aber stellen Sie sicher, dass Sie die richtige Variable / Funktion importieren.

Ich habe diesen Fehler erhalten

ImportError: Name IMPLICIT_WAIT kann nicht importiert werden

weil meine Variable eigentlich war IMPLICIT_TIMEOUT .

Als ich meinen Import geändert habe, um den richtigen Namen zu verwenden, wurde der Fehler 🤦‍♂️ nicht mehr angezeigt

Nick Brady
quelle
1
Ich war bereit, jemanden zu töten, um herauszufinden, warum from PIL import Pillowes nicht funktionierte. 😠
Aalaap
5

Wenn Sie importieren file1.pyaus file2.pyund verwendet diese:

if __name__ == '__main__':
    # etc

Variablen darunter file1.py können nicht importiert werden , file2.pyda __name__ dies nicht gleich ist __main__ !

Wenn Sie etwas von importieren möchten file1.pyzu file2.py, müssen Sie dies nutzen in file1.py:

if __name__ == 'file1':
    # etc

Geben Sie im Zweifelsfall eine assertErklärung ab, um festzustellen, ob__name__=='__main__'

Nicolas Gervais
quelle
4

Eine Möglichkeit, Importfehler zu verfolgen, besteht darin, Schritt für Schritt zu versuchen, Python für jede importierte Datei auszuführen, um eine fehlerhafte Datei aufzuspüren.

  1. Sie bekommen so etwas wie:

    python ./main.py

    ImportError: Name A kann nicht importiert werden

  2. dann starten Sie:

    python ./modules/a.py

    ImportError: Name B kann nicht importiert werden

  3. dann starten Sie:

    python ./modules/b.py

    ImportError: Name C kann nicht importiert werden (ein nicht vorhandenes Modul oder ein anderer Fehler)

Evalds Urtans
quelle
3

Auch nicht direkt relevant für das OP, aber wenn eine PyCharm Python-Konsole nach dem Hinzufügen eines neuen Objekts zu einem Modul nicht neu gestartet werden kann, ist dies auch eine gute Möglichkeit, sehr verwirrend zu werdenImportError: Cannot import name ...

Das verwirrende Teil ist , dass PyCharm wird der Import in der Konsole automatisch vervollständigt, aber der Import fehlschlägt dann.

djvg
quelle
2

Das Problem ist klar: Zirkuläre Abhängigkeit zwischen Namen in entityund physicsModulen.

Unabhängig davon, ob das gesamte Modul oder nur eine Klasse importiert wird, müssen die Namen geladen werden.

Sehen Sie sich dieses Beispiel an:

# a.py
import b
def foo():
  pass
b.bar()
# b.py
import a
def bar():
  pass
a.foo()

Dies wird zusammengestellt in:

# a.py
# import b
# b.py
# import a # ignored, already importing
def bar():
  pass
a.foo()
# name a.foo is not defined!!!
# import b done!
def foo():
  pass
b.bar()
# done!

Mit einer kleinen Änderung können wir dies lösen:

# a.py
def foo():
  pass
import b
b.bar()
# b.py
def bar():
  pass
import a
a.foo()

Dies wird zusammengestellt in:

# a.py
def foo():
  pass
# import b
# b.py
def bar():
  pass
# import a # ignored, already importing
a.foo()
# import b done!
b.bar()
# done!
DuniC
quelle
2

In meinem Fall arbeitete ich in einem Jupyter-Notizbuch 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.

Harry M.
quelle
1

Nicht speziell für diesen Fragesteller, aber der gleiche Fehler zeigt an, ob der Klassenname in Ihrem Import nicht mit der Definition in der Datei übereinstimmt, aus der Sie importieren.

Bennett
quelle