2012-02-12 10 views
258

Ho quattro diversi file denominati: main, vector, entity e physics. Non posterò tutto il codice, solo le importazioni, perché penso che sia lì dove si trova l'errore. (Se volete, posso pubblicare più)ImportError: impossibile importare il nome X

principale:

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

Entity:

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 

vettoriale:

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. 

Ho poi eseguito 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 a Python, ma ho lavorato con C++ per un lungo periodo. Immagino che l'errore sia dovuto all'importazione di entità due volte, una volta in main e più avanti in fisica, ma non conosco una soluzione alternativa. Qualcuno può aiutare?

+0

Qual è la struttura di directory di dove vengono memorizzati e in quale directory? – Ben

+0

dai un'occhiata a questa risposta per l'importazione di loop in python: http://stackoverflow.com/questions/7199466/how-to-break-import-loop-in-python – Gregor

+0

In generale, non è buona pratica di codifica fare 'da importazione ', o 'da importazione *'. Meglio importare sotto lo spazio dei nomi del modulo per evitare la possibilità di sovrascrivere riferimenti con nomi identici. –

risposta

285

Si dispone di importazioni dipendenti dalla circolare. physics.py viene importato da entity prima che la classe Ent sia definita e physics tenta di importare entity che è già in fase di inizializzazione. Rimuovere la dipendenza a physics dal modulo entity.

+1

Ok, capisco che la fisica sta importando entità che a sua volta importa la fisica. Ma, non posso rimuovere la dipendenza dalla fisica nell'entità, perché la classe Ent deve chiamarla per aggiornare la sua posizione. Cerco anche di importare la fisica alla fine del file o nel costruttore, e questo mi dà solo il NameError: il nome 'x' non è definito. – jsells

+3

Non c'è molto che si possa fare rispetto al refactoring del codice. Se non si fa riferimento a Physics in Ent constructor definition move mport appena sotto Ent. Se lo fai, aggiungi un metodo come setPhysics per abilitare l'importazione dopo il costruttore. –

+8

@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 per creare la struttura per le tue classi, inserisci anche il resto del codice. Quanto esattamente (in termini di codice) sono "Entità" e "Fisica" collegati tra loro? Sono sicuro che c'è una soluzione alternativa per quello che stai cercando di fare. –

-19

vostro principale dovrebbe essere in questo modo principale:

import time 
from entity import * 
from vector import * 
#the rest just creates an entity and prints the result of movement 
+10

L'importazione di questo tipo può rendere molto difficile capire da quale spazio dei nomi proviene una funzione bacata. Faresti molto meglio a importare solo quelli di cui hai bisogno per nome, in modo da preservare la tracciabilità. – Nate

-6

Python è case sensitive, quindi entity = Entity!. Ti suggerisco di cambiare la custodia di entity nelle tue importazioni per essere Entity. Questo risolverà il tuo problema.

+1

Questo non aiuta. Il nome del modulo è in realtà 'entity', come puoi vedere dal traceback (' entity.py'). Le dipendenze circolari da – cyroxx

86

Mentre si devono assolutamente evitare le dipendenze circolari, è possibile rinviare le importazioni in python.

ad esempio:

import SomeModule 

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

questo (almeno in alcuni casi) si aggirare l'errore.

+10

si aggirano meglio – ckb

58

Questa è una dipendenza circolare. Può essere risolto senza modifiche strutturali al codice. Il problema si verifica perché in vector si richiede che entity sia reso disponibile per l'uso immediatamente e viceversa. La ragione di questo problema è che tu chiedi di accedere ai contenuti 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 le dipendenze circolari e di impedire il ciclo infinito delle importazioni. In sostanza, tutto ciò che accade è che viene creato un segnaposto vuoto per il modulo (cioè non ha contenuto). Una volta compilati i moduli circolarmente dipendenti, aggiorna il modulo importato. Questo è qualcosa di simile a questo.

a = module() # import a 

# rest of module 

a.update_contents(real_a) 

per Python per essere in grado di lavorare con le dipendenze circolari è necessario utilizzare solo import x stile.

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

Dal momento che non si riferisce al contenuto del modulo al livello superiore, pitone può compilare il modulo senza effettivamente dover accedere al contenuto della dipendenza circolare. Per livello superiore intendo le righe che verranno eseguite durante la compilazione in contrasto con il contenuto delle funzioni (ad esempio y = x.y). Anche variabili statiche o di classe che accedono ai contenuti del modulo causeranno problemi.

7

Ho appena ricevuto questo errore troppo, per una ragione diversa ...

from my_sub_module import my_function 

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

3

To make logic clear is very important. This problem appear, because the reference become a dead loop.

Se non si desidera cambiare la logica, si può mettere la qualche dichiarazione di importazione che ha causato ImportError per l'altra posizione di 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() 

You will get Import Error: ImportError: cannot import name 'a1'

Ma se si cambia la posizione del test.b da importazione b2 in A come di seguito:

un .py

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

from test.b import b2 

E la possiamo ottenere ciò che vogliamo:

b1 
a1 
b2 
1

Basta aggiungere queste righe in fondo:

if __name__ == "__main__": 
    pass