ImportError: Não é possível importar o nome X

540

Eu tenho quatro arquivos diferentes nomeados: principal, vetor, entidade e física. Não vou postar todo o código, apenas as importações, porque acho que é aí que está o erro. (Se você quiser, posso postar mais)

A Principal:

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

Entidade:

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

Vetor:

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

Física:

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

Em seguida, corro de main.py e recebo o seguinte erro:

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

Eu sou muito novo em Python, mas trabalhei com C ++ por um longo tempo. Suponho que o erro se deva a importar a entidade duas vezes, uma na principal e mais tarde na física, mas não conheço uma solução alternativa. Alguém pode ajudar?

jsells
fonte
Qual é a estrutura de diretórios de onde eles estão armazenados e em quais diretórios?
1155 Ben Ben
1
dê uma olhada nesta resposta para importar loop em python: stackoverflow.com/questions/7199466/…
Gregor
Em geral, não é uma boa prática de codificação fazer from <module> import <name>ou from <modlue> import *. Melhor importar no espaço de nome do módulo para evitar a chance de substituir referências nomeadas de forma idêntica.
Joel Cornett
1
@jsells Você deve apenas chamar suas aulas Entitye, em Vectorvez de Ente Vect, não há razão para encurtar esses nomes. E sim, use import vectore então x = vector.Vector(0,0,0).
7
Hey @Kevin, como você conhece Java melhor, qual é a sua impressão deste artigo de 2008, onde a primeira frase do autor se refere a como as dependências circulares são "práticas bastante comuns" em Java?
HeyWatchThis

Respostas:

503

Você tem importações dependentes circulares. physics.pyé importado de entityantes da classe Entser definida e physicstenta importar entityque já está inicializando. Remova a dependência physicsdo entitymódulo.

Teemu Ikonen
fonte
5
Não há muito que você possa fazer além de refatorar seu código. Se você não consultar a definição do construtor Physics in Ent, mova mport logo abaixo do Ent. Se você fizer isso, adicione um método como setPhysics para ativar a importação após o construtor.
Teemu Ikonen
12
@jsells Como você trabalha com C ++ "há muito tempo", você deve saber que duas classes NUNCA devem depender umas das outras. Isso é extremamente importante em C ++ e, mesmo que não seja a coisa nº 1 em Python, ainda é uma boa idéia seguir essa regra. Nunca tenha duas classes que se conhecem, nunca. Se você precisar de ajuda para criar a estrutura para suas classes, poste o restante do código também. Como exatamente (em termos de código) estão Entitye estão Physicsligados um ao outro? Tenho certeza de que há uma solução alternativa para o que você está tentando fazer.
7
@ user2032433 Isso realmente depende do que você quer dizer com 'conhecer um ao outro'. É verdade que um bom design geralmente produz uma árvore de dependências unidirecionais e essa normalmente é a melhor abordagem. Mas há exceções a isso. As classes C ++ certamente podem se referir uma à outra circularmente. (Embora seja impossível que eles sejam compostos um do outro.) Sem declaração direta, esse é um problema no Python que nem sempre tem uma solução C ++.
John McFarlane
93
A afirmação "duas classes NUNCA devem depender uma da outra" é um lixo. A navegação bidirecional (bidirecional) é muito comum na orientação a objetos. books.google.co.uk/…
Martin Spamer
5
O padrão de design do Estado (por exemplo) geralmente é implementado com uma classe Context e uma interface State. As instâncias de estado recebem a instância Context para que possam chamar setState. Isso requer que o Estado conheça o contexto e vice-versa. Como essa construção clássica é "ruim no código"? Na verdade, esse é exatamente o problema com o qual estou lutando em Python, mas não era necessário quando implementei State em Java.
Auspice
142

Embora você deva definitivamente evitar dependências circulares, você pode adiar as importações em python.

por exemplo:

import SomeModule

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

isso (pelo menos em alguns casos) contornará o erro.

bharling
fonte
38
dependências circulares são melhor contornadas
ckb
4
Base pep8, colocando importação método dentro não é boa prática
TomSawyer
@TomSawyer Por quê?
Kröw 3/11/19
@ TomSawyer Eu não recomendo isso, mas é uma solução rápida que pode tirar você do sério
complicada bharling
117

Esta é uma dependência circular. Pode ser resolvido sem nenhuma modificação estrutural no código. O problema ocorre porque vectorvocê exige que entityseja disponibilizado para uso imediato e vice-versa. A razão para esse problema é que você está pedindo para acessar o conteúdo do módulo antes de ele estar pronto - usando from x import y. Isto é essencialmente o mesmo que

import x
y = x.y
del x

O Python é capaz de detectar dependências circulares e impedir o loop infinito de importações. Essencialmente, tudo o que acontece é que um espaço reservado vazio é criado para o módulo (ou seja, não possui conteúdo). Após a compilação dos módulos circularmente dependentes, ele atualiza o módulo importado. Isso funciona mais ou menos assim.

a = module() # import a

# rest of module

a.update_contents(real_a)

Para que o python possa trabalhar com dependências circulares, você deve usar import xapenas o estilo.

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

Como você não está mais se referindo ao conteúdo do módulo no nível superior, o python pode compilar o módulo sem precisar acessar o conteúdo da dependência circular. Por nível superior, quero dizer linhas que serão executadas durante a compilação, em oposição ao conteúdo das funções (por exemplo,y = x.y ). Variáveis ​​estáticas ou de classe que acessam o conteúdo do módulo também causarão problemas.

Dunas
fonte
24

Tornar a lógica clara é muito importante. Esse problema aparece, porque a referência se torna um loop morto.

Se você não quiser alterar a lógica, poderá colocar alguma instrução de importação que causou ImportError na outra posição do arquivo, por exemplo, no final.

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

Você receberá um erro de importação: ImportError: cannot import name 'a1'

Mas se mudarmos a posição de test.b import b2 em A, como abaixo:

a.py

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

from test.b import b2

E nós podemos obter o que queremos:

b1
a1
b2
g10guang
fonte
18

Esta é uma dependência circular. podemos resolver esse problema usando o módulo de importação ou classe ou função onde precisávamos. se usarmos essa abordagem, podemos corrigir a dependência circular

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
fonte
17

Acabei de receber esse erro também, por um motivo diferente ...

from my_sub_module import my_function

O script principal tinha finais de linha do Windows. my_sub_moduleteve terminações de linha UNIX. Mudá-los para serem os mesmos corrigiu o problema. Eles também precisam ter a mesma codificação de caracteres.

marengaz
fonte
7

Como já mencionado, isso é causado por uma dependência circular . O que não foi mencionado é que, quando você está usando o módulo de digitação Python e importa uma classe apenas para ser usada para anotar tipos , pode usar referências de encaminhamento :

Quando uma dica de tipo contém nomes que ainda não foram definidos, essa definição pode ser expressa como uma string literal, a ser resolvida posteriormente.

e remova a dependência (a importação ), por exemplo, em vez de

from my_module import Tree

def func(arg: Tree):
    # code

Faz:

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

(observe a importdeclaração removida )

Tomasz Bartkowiak
fonte
6

Não nomeie seu script python atual com o nome de outro módulo que você importa

Solução: renomeie seu script python em funcionamento

Exemplo:

  1. você está trabalhando em medicaltorch.py
  2. nesse script, você tem: from medicaltorch import datasets as mt_datasetsonde medicaltorchdeve ser um módulo instalado

Isso falhará com o ImportError. Apenas renomeie seu script python em funcionamento em 1.

Paulo
fonte
Obrigado, isso resolve o problema que eu tinha. Eu usei a biblioteca colorama e nomeei o arquivo colorama.py, para que o python não soubesse o que importar. Alterar o nome do arquivo ajuda.
Marek Bodziony 04/03
5

Ainda não o vejo aqui - isso é incrivelmente estúpido, mas certifique-se de importar a variável / função correta.

Eu estava recebendo esse erro

ImportError: não é possível importar o nome IMPLICIT_WAIT

porque minha variável era realmente IMPLICIT_TIMEOUT.

quando alterei minha importação para usar o nome correto, não recebi mais o erro 🤦‍♂️

Nick Brady
fonte
1
Eu estava pronto para matar alguém tentando descobrir por que from PIL import Pillownão estava funcionando. A
aalaap 6/02/19
5

Se você está importando file1.pyde file2.pye usou isso:

if __name__ == '__main__':
    # etc

As variáveis ​​abaixo disso em file1.py não podem ser importadas para, file2.pyporque __name__ não é igual __main__ !

Se você deseja importar algo de file1.pypara file2.py, precisará usá-lo em file1.py:

if __name__ == 'file1':
    # etc

Em caso de dúvida, faça uma assertdeclaração para determinar se__name__=='__main__'

Nicolas Gervais
fonte
4

Uma maneira de rastrear o erro de importação é passo a passo, tentando executar o python em cada um dos arquivos importados para rastrear um erro ruim.

  1. você obtém algo como:

    python ./main.py

    ImportError: não é possível importar o nome A

  2. então você lança:

    python ./modules/a.py

    ImportError: não é possível importar o nome B

  3. então você lança:

    python ./modules/b.py

    ImportError: não é possível importar o nome C (algum módulo NÃO Existente ou algum outro erro)

Evalds Urtans
fonte
3

Também não é diretamente relevante para o OP, mas falhar em reiniciar um console PyCharm Python, após adicionar um novo objeto a um módulo, também é uma ótima maneira de obter uma solução muito confusa.ImportError: Cannot import name ...

A parte confusa é que PyCharm irá completar automaticamente a importação no console, mas a importação, em seguida, falha.

djvg
fonte
2

O problema é claro: dependência circular entre nomes entitye physicsmódulos.

Independentemente de importar o módulo inteiro ou apenas uma classe, os nomes devem ser carregados.

Veja este exemplo:

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

Isso será compilado em:

# 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!

Com uma pequena alteração, podemos resolver isso:

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

Isso será compilado em:

# 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
fonte
2

No meu caso, eu estava trabalhando em um bloco de anotações Jupyter e isso estava acontecendo devido à importação já estar em cache desde que eu defini a classe / função dentro do meu arquivo de trabalho.

Eu reiniciei meu kernel Jupyter e o erro desapareceu.

Harry M
fonte
1

Não especificamente para esse solicitante, mas esse mesmo erro será exibido se o nome da classe na sua importação não corresponder à definição no arquivo do qual você está importando.

Bennett
fonte