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?


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.


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.


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.


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

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

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.


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 )


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.


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 🤦‍♂️


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__'


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)


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.


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!

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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.