AttributeError: el objeto 'módulo' no tiene atributo

193

Tengo dos módulos de 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"

Cuando corro a.py, obtengo:

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

¿Qué significa el error? ¿Cómo lo soluciono?

Stephen Hsu
fuente
Tenga en cuenta que sus preguntas son muy similares a esta respuesta. Al parecer, el código en esta respuesta funciona solo encontrar, pero el tuyo no? stackoverflow.com/a/7336880/565879
Botones840

Respuestas:

188

Tiene importaciones mutuas de alto nivel, lo que casi siempre es una mala idea.

Si realmente debe tener importaciones mutuas en Python, la forma de hacerlo es importarlas dentro de una función:

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

Ahora a.py puede hacerlo de forma segura import bsin causar problemas.

(A primera vista, puede parecer que cause_a_to_do_something()sería muy ineficiente porque lo hace importcada vez que lo llama, pero de hecho, el trabajo de importación solo se realiza la primera vez. La segunda y posteriores veces que importa un módulo, es una operación rápida. )

RichieHindle
fuente
92

También he visto este error al nombrar inadvertidamente un módulo con el mismo nombre que uno de los módulos estándar de Python. Por ejemplo, tenía un módulo llamado commandsque también es un módulo de biblioteca de Python. Esto resultó difícil de rastrear, ya que funcionó correctamente en mi entorno de desarrollo local, pero falló con el error especificado cuando se ejecutaba en Google App Engine.

lucrussell
fuente
42

El problema es la dependencia circular entre los módulos. aimportaciones be bimportaciones a. Pero uno de ellos debe cargarse primero; en este caso, Python termina inicializando el módulo aantes by b.hi()aún no existe cuando intenta acceder a él a.

algo
fuente
21

Obtuve este error haciendo referencia a una enumeración que se importó de manera incorrecta, por ejemplo:

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

Importación correcta:

from package.MyEnumClass import MyEnumClass

Espero que ayude a alguien

Stoyan
fuente
7

Experimenté este error porque el módulo no se importó realmente. El código se veía así:

import a.b, a.c

# ...

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

La última línea resultó en un AttributeError. La causa fue que no noté que los submódulos de a( a.by a.c) fueron importados explícitamente , y asumí que la importdeclaración realmente importaba a.

Dag Høidahl
fuente
6

Me enfrenté al mismo problema. arreglado mediante el uso reload.

import the_module_name
from importlib import reload
reload(the_module_name)
Solo nosotros
fuente
5

Me encontré con este problema cuando revisé una versión anterior de un repositorio de git. Git reemplazó mis .pyarchivos, pero dejó los .pycarchivos sin seguimiento . Como los .pyarchivos y los .pycarchivos no estaban sincronizados, el importcomando en un .pyarchivo no pudo encontrar el módulo correspondiente en los .pycarchivos.

La solución fue simplemente eliminar los .pycarchivos y dejar que se regeneren automáticamente.

craq
fuente
Puede usar este comando para eliminar todos los .pycarchivos:find . -name "*.pyc" -exec rm -f {} \;
Ollie
4

en ubuntu 18.04 ( virtualenv , python.3.6.x ), el siguiente fragmento de recarga resolvió el problema para mí:

main.py

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

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

dónde:

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

para más verificación de documentación : aquí

Behzad Sezari
fuente
3

Todas las respuestas anteriores son geniales, pero me gustaría hablar aquí. Si no detectó ningún problema mencionado anteriormente, intente aclarar su entorno de trabajo. Funcionó para mi.

Jian
fuente
0

No estoy seguro de cómo, pero el cambio a continuación solucionó mi problema:

Tenía el nombre del archivo y el nombre de la misma importación, por ejemplo, tenía el nombre del archivo como emoji.py e intentaba importar emoji. Pero cambiar el nombre del archivo resolvió el problema.

Espero que ayude

MD5
fuente
0

Las importaciones circulares causan problemas, pero Python tiene formas de mitigarlo incorporado.

El problema es cuando se ejecuta python a.py, se ejecuta a.pypero no se marca como importado como módulo. Entonces, a su vez a.py-> importa el módulo b -> importa el módulo a -> importa el módulo b. La última importación es no operativa ya que b se está importando actualmente y Python protege contra eso. Y b es un módulo vacío por ahora. Entonces cuando se ejecutab.hi() , no puede encontrar nada.

Tenga en cuenta que lo b.hi()que se ejecutó es durante a.py-> módulo b -> módulo a, no a.pydirectamente.

En su ejemplo específico, puede ejecutar python -c 'import a'en el nivel superior, por lo que la primera ejecución de a.pyse registra como la importación de un módulo.

Hot.PxL
fuente
0

El orden de importación fue la razón por la que tenía 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

Solo otro ejemplo de cómo se vería, similar a la respuesta de RichieHindie, pero con clases.

jmunsch
fuente
0

Me he cruzado con este problema muchas veces, pero no intenté profundizar más al respecto. Ahora entiendo el problema principal.

Esta vez mi problema fue importar serializadores (django y restframework) desde diferentes módulos como los siguientes:

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

Estaba teniendo un problema como este:

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

Lo que quería lograr era lo siguiente:

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

Entonces, como se menciona en las líneas anteriores sobre cómo resolverlo (importación de nivel superior), procedo a hacer los siguientes cambios:

# 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

Por lo tanto, django runserver se ejecutó sin 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.

El estado final de las líneas de código fue el siguiente:

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 esto pueda ser útil para todos los demás.

Saludos,

Manuel Lazo
fuente
0

En mi caso, trabajando con python 2.7 con numpy versión 1.15.0, funcionó con

pip install statsmodels=="0.10.0"
Mondaa
fuente