ImportError: impossibile importare il nome X


540

Ho quattro diversi file denominati: principale, vettore, entità e fisica. Non pubblicherò tutto il codice, ma solo le importazioni, perché penso che sia lì che si trova l'errore. (Se vuoi, posso postare di più)

Principale:

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

Entità:

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

Vettore:

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

Fisica:

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

Quindi corro da main.py e ottengo il seguente errore:

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

Sono molto nuovo in Python ma ho lavorato a lungo con C ++. Immagino che l'errore sia dovuto all'importazione dell'entità due volte, una volta nella parte principale e in seguito nella fisica, ma non conosco una soluzione alternativa. Qualcuno può aiutare?


Qual è la struttura di directory di dove sono memorizzati e in quali directory?
Ben

1
dai un'occhiata a questa risposta per importare in loop in Python: stackoverflow.com/questions/7199466/…
Gregor

In generale, non è una buona pratica di codifica fare from <module> import <name>, o from <modlue> import *. Meglio importare nello spazio dei nomi del modulo per evitare la possibilità di sovrascrivere riferimenti identici.
Joel Cornett,

1
@jsells Dovresti semplicemente chiamare le tue classi Entitye Vectorinvece di Ente Vect, non c'è motivo di abbreviare tali nomi. E sì, usa import vectore poi x = vector.Vector(0,0,0).

7
Ehi @Kevin dato che conosci meglio Java, qual è la tua impressione di questo articolo del 2008 in cui la prima frase dell'autore si riferisce a come le dipendenze circolari sono "pratica piuttosto comune" in Java?
HeyWatch, questo

Risposte:


503

Hai importazioni dipendenti circolari. physics.pyviene importato da entityprima che la classe Entsia definita e physicstenta di importare entityche è già in fase di inizializzazione. Rimuovere la dipendenza physicsdal entitymodulo.


5
Non c'è molto altro da fare se non il refactoring del codice. Se non fai riferimento a Fisica nella definizione del costruttore Ent sposta mport appena sotto Ent. Se lo fai, aggiungi un metodo come setPhysics per abilitare l'importazione dopo il costruttore.
Teemu Ikonen,

12
@jsells Dato che hai lavorato con C ++ "per molto tempo", dovresti sapere che due classi non dovrebbero MAI dipendere l'una dall'altra. Questo è estremamente importante in C ++ e anche se non è la cosa numero 1 in Python, è comunque una buona idea seguire questa regola. Mai due classi che si conoscono, mai. Se hai bisogno di aiuto con la creazione della struttura per le tue classi, pubblica anche il resto del codice. Come sono esattamente (in termini di codice) Entitye Physicscollegati tra loro? Sono sicuro che esiste una soluzione alternativa per quello che stai cercando di fare.

7
@ user2032433 Dipende molto da cosa intendi per 'conoscerci'. È vero che un buon design di solito produce un albero di dipendenze a senso unico e questo è normalmente l'approccio migliore. Ma ci sono eccezioni a questo. Le classi C ++ possono certamente riferirsi l'una all'altra in modo circolare. (Sebbene sia impossibile per loro essere composti l'uno dall'altro.) Senza dichiarazione anticipata, questo è un problema in Python che non ha sempre una soluzione C ++.
John McFarlane,

93
L'affermazione "due classi non devono MAI dipendere l'una dall'altra" è spazzatura. La navigazione bidirezionale (bidirezionale) è molto comune nell'orientamento agli oggetti. books.google.co.uk/…
Martin Spamer,

5
Il modello di progettazione dello stato (ad esempio) viene solitamente implementato con una classe Context e un'interfaccia State. Le istanze di stato vengono passate all'istanza Context in modo che possano chiamare setState. Ciò richiede che lo Stato sia a conoscenza del contesto e viceversa. In che modo questo costrutto classico è "cattivo nel codice"? In realtà questo è esattamente il problema con cui sto lottando in Python, ma non è stato necessario quando ho implementato State in Java.
Auspice,

142

Mentre dovresti assolutamente evitare dipendenze circolari, puoi rinviare le importazioni in Python.

per esempio:

import SomeModule

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

questo (almeno in alcuni casi) eluderà l'errore.


38
Le dipendenze circolari sono meglio eluse
ckb

4
Basata su pep8, l'importazione all'interno del metodo non è una buona pratica
TomSawyer,

@TomSawyer Perché?
Kröw,

@TomSawyer Non lo consiglio, ma è una soluzione rapida che può farti uscire da un bind
bharling

117

Questa è una dipendenza circolare. Può essere risolto senza alcuna modifica strutturale al codice. Il problema si verifica perché nella vectorrichiesta è entitynecessario renderlo immediatamente disponibile per l'uso e viceversa. Il motivo di questo problema è che stai chiedendo di accedere al contenuto del modulo prima che sia pronto, usando from x import y. Questo è essenzialmente lo stesso di

import x
y = x.y
del x

Python è in grado di rilevare dipendenze circolari e impedire il ciclo infinito di importazioni. Sostanzialmente tutto ciò che accade è che viene creato un segnaposto vuoto per il modulo (cioè non ha contenuto). Una volta compilati i moduli dipendenti circolarmente, aggiorna il modulo importato. Funziona in questo modo.

a = module() # import a

# rest of module

a.update_contents(real_a)

Affinché python sia in grado di funzionare con dipendenze circolari è necessario utilizzare import xsolo lo stile.

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

Dal momento che non ti riferisci più al contenuto del modulo al livello superiore, python può compilare il modulo senza effettivamente accedere al contenuto della dipendenza circolare. Per livello superiore intendo le linee che verranno eseguite durante la compilazione rispetto al contenuto delle funzioni (ad es. y = x.y). Anche le variabili statiche o di classe che accedono ai contenuti del modulo causeranno problemi.


24

Per chiarire la logica è molto importante. Questo problema si presenta perché il riferimento diventa un loop morto.

Se non si desidera modificare la logica, è possibile inserire alcune istruzioni di importazione che hanno causato ImportError nell'altra posizione del file, ad esempio la fine.

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

Si otterrà un errore di importazione: ImportError: cannot import name 'a1'

Ma se cambiamo la posizione di da test.b importiamo b2 in A come di seguito:

a.py

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

from test.b import b2

E possiamo ottenere ciò che vogliamo:

b1
a1
b2

18

Questa è una dipendenza circolare. possiamo risolvere questo problema usando il modulo di importazione o la classe o la funzione dove ne avevamo bisogno. se utilizziamo questo approccio, possiamo correggere la dipendenza circolare

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

17

Ho appena ricevuto anche questo errore, per un motivo diverso ...

from my_sub_module import my_function

Lo script principale aveva terminazioni di riga di Windows. my_sub_moduleaveva terminazioni di linea UNIX. Modificandoli per essere lo stesso risolto il problema. Devono anche avere la stessa codifica dei caratteri.


7

Come già accennato, questo è causato da una dipendenza circolare . Ciò che non è stato menzionato è che quando si utilizza il modulo di digitazione Python e si importa una classe da utilizzare solo per annotare Tipi , è possibile utilizzare i riferimenti Forward :

Quando un suggerimento sul tipo contiene nomi che non sono stati ancora definiti, tale definizione può essere espressa come una stringa letterale, da risolvere in seguito.

e rimuovere la dipendenza (l' importazione ), ad esempio invece di

from my_module import Tree

def func(arg: Tree):
    # code

fare:

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

(notare l' importistruzione rimossa )


6

Non nominare il tuo attuale script Python con il nome di qualche altro modulo che importi

Soluzione: rinominare lo script Python funzionante

Esempio:

  1. stai lavorando medicaltorch.py
  2. in quello script hai: from medicaltorch import datasets as mt_datasetsdove medicaltorchdovrebbe essere un modulo installato

Questo fallirà con il ImportError. Rinomina il tuo script Python funzionante in 1.


Grazie, questo risolve il problema che ho avuto. Ho usato la libreria colorama e ho chiamato il file colorama.py, quindi Python non sapeva cosa importare. La modifica del nome del file aiuta.
Marek Bodziony,

5

Non lo vedi ancora qui - è incredibilmente stupido, ma assicurati di importare la variabile / funzione corretta.

Stavo ricevendo questo errore

ImportError: impossibile importare il nome IMPLICIT_WAIT

perché la mia variabile era in realtà IMPLICIT_TIMEOUT.

quando ho cambiato la mia importazione per usare il nome corretto, non ho più ricevuto l'errore 🤦‍♂️


1
Ero pronto a uccidere qualcuno cercando di capire perché from PIL import Pillownon funzionava. 😠
aalaap

5

Se si sta importando file1.pyda file2.pye usato questo:

if __name__ == '__main__':
    # etc

Le variabili inferiore a quello file1.py , non possono essere importati a file2.pycausa __name__ non è uguale __main__ !

Se vuoi importare qualcosa da file1.pya file2.py, devi usarlo in file1.py:

if __name__ == 'file1':
    # etc

In caso di dubbio, fare una assertdichiarazione per determinare se__name__=='__main__'


4

Un modo per tenere traccia dell'errore di importazione è passo dopo passo cercando di eseguire Python su ciascuno dei file importati per rintracciarne uno difettoso.

  1. ottieni qualcosa del tipo:

    python ./main.py

    ImportError: impossibile importare il nome A

  2. quindi si avvia:

    python ./modules/a.py

    ImportError: impossibile importare il nome B

  3. quindi si avvia:

    python ./modules/b.py

    ImportError: impossibile importare il nome C (alcuni moduli NON esistenti o altri errori)


3

Inoltre, non direttamente rilevante per l'OP, ma non riuscire a riavviare una console PyCharm Python, dopo aver aggiunto un nuovo oggetto a un modulo, è anche un ottimo modo per ottenere unImportError: Cannot import name ...

La parte confusa è che PyCharm completerà automaticamente l'importazione nella console, ma l'importazione non riuscirà .


2

Il problema è chiaro: dipendenza circolare tra nomi entitye physicsmoduli.

Indipendentemente dall'importazione dell'intero modulo o solo di una classe, i nomi devono essere caricati.

Guarda questo esempio:

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

Questo sarà compilato 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!

Con una leggera modifica possiamo risolvere questo:

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

Questo sarà compilato 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!

2

Nel mio caso, stavo lavorando su un notebook Jupyter e questo stava accadendo a causa dell'importazione già in cache da quando avevo definito la classe / funzione all'interno del mio file di lavoro.

Ho riavviato il mio kernel Jupyter e l'errore è scomparso.


1

Non specificamente per questo richiedente, ma questo stesso errore mostrerà se il nome della classe nella tua importazione non corrisponde alla definizione nel file da cui stai importando.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.