AttributeError: o objeto 'module' não tem atributo

193

Eu tenho dois módulos python:

a.py

import b

def hello():
  print "hello"

print "a.py"
print hello()
print b.hi()

b.py

import a

def hi():
  print "hi"

Quando corro a.py, recebo:

AttributeError: 'module' object has no attribute 'hi'

O que significa o erro? Como faço para corrigir isso?

Stephen Hsu
fonte
Observe que suas perguntas são muito semelhantes a esta resposta. Aparentemente, o código nesta resposta funciona apenas para encontrar, mas o seu não? stackoverflow.com/a/7336880/565879
Buttons840

Respostas:

188

Você tem importações mútuas de nível superior, o que quase sempre é uma má idéia.

Se você realmente deve ter importações mútuas no Python, a maneira de fazer isso é importá-las dentro de uma função:

# In b.py:
def cause_a_to_do_something():
    import a
    a.do_something()

Agora o a.py pode fazer com segurança import bsem causar problemas.

(À primeira vista, pode parecer que cause_a_to_do_something()seria imensamente ineficiente, porque é feito importtoda vez que você o chama, mas, na verdade, o trabalho de importação é feito apenas na primeira vez. Na segunda e subsequente importação de um módulo, é uma operação rápida. )

RichieHindle
fonte
92

Também vi esse erro ao nomear inadvertidamente um módulo com o mesmo nome que um dos módulos Python padrão. Por exemplo, eu tive um módulo chamado, commandsque também é um módulo de biblioteca Python. Foi difícil rastrear isso, pois funcionava corretamente no meu ambiente de desenvolvimento local, mas falhou com o erro especificado ao ser executado no Google App Engine.

lucrussell
fonte
42

O problema é a dependência circular entre os módulos. aimportações be bimportações a. Mas um deles precisa ser carregado primeiro - nesse caso, o python acaba inicializando o módulo aantes be b.hi()ainda não existe quando você tenta acessá-lo a.

sth
fonte
21

Eu recebi esse erro referenciando uma enumeração que foi importada de maneira errada, por exemplo:

from package import MyEnumClass
# ...
# in some method:
return MyEnumClass.Member

Importação correta:

from package.MyEnumClass import MyEnumClass

Espero que ajude alguém

Stoyan
fonte
7

Ocorreu este erro porque o módulo não foi realmente importado. O código ficou assim:

import a.b, a.c

# ...

something(a.b)
something(a.c)
something(a.d)  # My addition, which failed.

A última linha resultou em um AttributeError. A causa foi que eu não percebi que os submódulos de a( a.be a.c) foram explicitamente importados e assumi que a importinstrução realmente era importada a.

Dag Høidahl
fonte
6

Eu enfrentei o mesmo problema. corrigido usando reload.

import the_module_name
from importlib import reload
reload(the_module_name)
Apenas nós
fonte
Obrigado, esta é a única resposta que funcionou para mim :)
TheTechRobo36414519
5

Eu me deparei com esse problema quando fiz o check-out de uma versão mais antiga de um repositório do git. O Git substituiu meus .pyarquivos, mas deixou os .pycarquivos não rastreados . Como os .pyarquivos e .pycarquivos estavam fora de sincronia, o importcomando em um .pyarquivo não pôde encontrar o módulo correspondente nos .pycarquivos.

A solução foi simplesmente excluir os .pycarquivos e permitir que eles sejam regenerados automaticamente.

craq
fonte
Você pode usar este comando para excluir todos os .pycarquivos:find . -name "*.pyc" -exec rm -f {} \;
Ollie
4

no ubuntu 18.04 ( virtualenv , python.3.6.x ), o seguinte snippet de recarga resolveu o problema para mim:

main.py

import my_module  # my_module.py
from importlib import reload # reload 
reload(my_module)

print(my_module)
print(my_modeule.hello())

Onde:

|--main.py    
|--my_module.py

para mais documentação, consulte: aqui

Behzad Sezari
fonte
3

Todas as respostas acima são ótimas, mas eu gostaria de comentar aqui. Se você não encontrou nenhum problema mencionado acima, tente limpar o seu ambiente de trabalho. Funcionou para mim.

Jian
fonte
0

Não sei como, mas a alteração abaixo classificou meu problema:

Eu estava tendo o nome do arquivo e o mesmo nome de importação, por exemplo, tinha o nome do arquivo como emoji.py e estava tentando importar emoji. Mas alterar o nome do arquivo resolveu o problema.

Espero que ajude

MD5
fonte
0

As importações circulares causam problemas, mas o Python tem maneiras de atenuá-lo.

O problema é que, quando você executa python a.py, ele é executado, a.pymas não o marca como importado como módulo. Então, por sua vez a.py-> módulo de importação b -> módulo de importação a -> módulo de importação b. A última importação a no-op desde que b está sendo importada e o Python protege contra isso. E b é um módulo vazio por enquanto. Então, quando ele executab.hi() , não consegue encontrar nada.

Observe que o b.hi()que foi executado ocorre durante a.py-> módulo b -> módulo a, não ema.py diretamente.

No seu exemplo específico, você pode simplesmente executar python -c 'import a'no nível superior, para que a primeira execução de a.pyseja registrada como importando um módulo.

Hot.PxL
fonte
0

A ordem da importação foi a razão pela qual eu estava tendo problemas:

a.py:

############
# this is a problem
# move this to below
#############
from b import NewThing

class ProblemThing(object):
    pass

class A(object):
   ###############
   # add it here
   # from b import NewThing
   ###############
   nt = NewThing()
   pass

b.py:

from a import ProblemThing

class NewThing(ProblemThing):
    pass

Apenas mais um exemplo de como isso pode parecer, semelhante à resposta de RichieHindie, mas com classes.

jmunsch
fonte
0

Já enfrentei esse problema muitas vezes, mas não tentei me aprofundar mais. Agora eu entendo a questão principal.

Dessa vez, meu problema foi importar serializadores (django e restframework) de diferentes módulos, como os seguintes:

from rest_framework import serializers

from common import serializers as srlz
from prices import models as mdlpri

# the line below was the problem 'srlzprod'
from products import serializers as srlzprod

Eu estava tendo um problema como este:

from product import serializers as srlzprod
ModuleNotFoundError: No module named 'product'

O que eu queria realizar era o seguinte:

class CampaignsProductsSerializers(srlz.DynamicFieldsModelSerializer):
    bank_name = serializers.CharField(trim_whitespace=True,)
    coupon_type = serializers.SerializerMethodField()
    promotion_description = serializers.SerializerMethodField()

    # the nested relation of the line below
    product = srlzprod.ProductsSerializers(fields=['id','name',],read_only=True,)

Portanto, conforme mencionado nas linhas acima, como resolvê-lo (importação de nível superior), procedo às seguintes alterações:

# change
product = srlzprod.ProductsSerializers(fields=['id','name',],read_only=True,)
# by 
product = serializers.SerializerMethodField()

# and create the following method and call from there the required serializer class
def get_product(self, obj):
        from products import serializers as srlzprod
        p_fields = ['id', 'name', ]
        return srlzprod.ProductsSerializers(
            obj.product, fields=p_fields, many=False,
        ).data

Portanto, o django runserver foi executado sem problemas:

./project/settings/manage.py runserver 0:8002 --settings=settings_development_mlazo
Performing system checks...

System check identified no issues (0 silenced).
April 25, 2020 - 13:31:56
Django version 2.0.7, using settings 'settings_development_mlazo'
Starting development server at http://0:8002/
Quit the server with CONTROL-C.

O estado final das linhas de código foi o seguinte:

from rest_framework import serializers

from common import serializers as srlz
from prices import models as mdlpri

class CampaignsProductsSerializers(srlz.DynamicFieldsModelSerializer):
    bank_name = serializers.CharField(trim_whitespace=True,)
    coupon_type = serializers.SerializerMethodField()
    promotion_description = serializers.SerializerMethodField()
    product = serializers.SerializerMethodField()

    class Meta:
        model = mdlpri.CampaignsProducts
        fields = '__all__'

    def get_product(self, obj):
        from products import serializers as srlzprod
        p_fields = ['id', 'name', ]
        return srlzprod.ProductsSerializers(
            obj.product, fields=p_fields, many=False,
        ).data

Espero que isso possa ser útil para todos os outros.

Saudações,

Manuel Lazo
fonte
0

No meu caso, trabalhando com python 2.7 com numpy versão 1.15.0, ele trabalhou com

pip install statsmodels=="0.10.0"
Mondaa
fonte