属性错误: 'module'对象没有属性

252

I have two python modules:

a.py

import b

def hello():
  print "hello"

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

b.py

import a

def hi():
  print "hi"

当我运行a.py时,我得到了以下结果:
AttributeError: 'module' object has no attribute 'hi'

这个错误的意思是什么?我该怎么修复它?


请注意,您的问题与此答案非常相似。显然,此答案中的代码可以正常工作,但是您的代码不能?https://dev59.com/GGs05IYBdhLWcg3wR_63#7336880 - Buttons840
20个回答

242

你有相互的顶级导入,这几乎总是一个坏主意。

如果你真的必须在Python中使用相互导入,正确的方法是在函数内部导入它们:

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

现在,a.py可以安全地执行import b而不会引起问题。

(乍一看,cause_a_to_do_something()似乎非常低效,因为每次调用它时都要进行一次import,但实际上只有第一次才会进行导入工作。第二次和随后的导入模块是一项快速操作。)


7
在我看来,这更像是一种解决方法而不是一个解决方案。 - gst
5
@gst 所以基本上就像所有用 Python 写的东西一样? - clockw0rk

117

当我无意中将模块命名为与标准 Python 模块名称相同的名称时,我也曾遇到过这个错误。例如,我有一个名为 commands 的模块,它也是 Python 库模块。在我的本地开发环境中,它可以正常工作,但在 Google App Engine 上运行时会出现指定的错误,这证明了这个问题很难跟踪。


54

问题是模块之间存在循环依赖。 a 导入了 b,而 b 又导入了 a。但其中一个模块需要先被加载 - 在这种情况下,Python 会在初始化模块 b 之前初始化模块 a,当您在 a 中尝试访问 b.hi() 时,它还不存在。


28

我因为引用了一个枚举类型,但是引入的方式不正确导致出现了这个错误,例如:

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

正确的导入:

from package.MyEnumClass import MyEnumClass

希望这能对某些人有所帮助


10

我遇到了同样的问题,通过使用 reload 命令解决了这个问题。

import the_module_name
from importlib import reload
reload(the_module_name)

这真的很有趣,你有什么想法为什么模块的某些部分可能会丢失? - Anscandance

8
ubuntu 18.04virtualenv, python.3.6.x)上,以下 reload 片段对我解决了问题:

main.py

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

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

where:

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

如需更多文档,请查看:此处


7
当我从git检出一个旧版本的存储库时,遇到了这个问题。Git替换了我的.py文件,但是未跟踪的.pyc文件被保留了下来。由于.py文件和.pyc文件不同步,在.py文件中使用import命令时无法在.pyc文件中找到相应的模块。
解决方案很简单,只需删除.pyc文件,让它们自动重新生成即可。

你可以使用以下命令删除所有的.pyc文件:find . -name "*.pyc" -exec rm -f {} \; - Ollie

6

我遇到了这个错误,因为模块实际上没有被导入。代码看起来像这样:

import a.b, a.c

# ...

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

最后一行导致了一个AttributeError。原因是我没有注意到a的子模块(a.b和a.c)被明确地导入了,并且假设import语句实际上导入了a。

5

以上所有答案都很好,但我想在这里插一句话。如果您没有发现上述提到的任何问题,请尝试清理您的工作环境。这对我很有效。


补充一下这个答案:当Jian说“清理你的工作环境”时,如果你在Jupyter笔记本中,只需“关闭”你的工作.ipynb文件(而不是环境或机器),然后再次打开你的.ipynb文件即可,这对我很有效。 - Ellery Leung
请重新启动您的IDA内核,因为并非所有人都在使用Jupyter。 - gregV

4
循环导入会引起问题,但Python内置了缓解这个问题的方式。 问题出在运行python a.py时,它运行了a.py但没有将其标记为已导入模块。 因此,a.py -> 导入模块b -> 导入模块a -> 导入模块b。 最后一个导入语句是无效的,因为b目前正在被导入并且Python防止这种情况发生。 而此时b是一个空模块。 因此,在执行b.hi()时,找不到任何内容。
请注意,执行的b.hi()是在a.py-> 模块b-> 模块a期间完成的,而不是直接在a.py中完成。
在您的特定示例中,您可以在顶层运行python -c 'import a',以便第一次执行a.py被注册为导入模块。

1
这是我个人认为的正确答案。解释得非常清楚。 - gst
我想补充一点,当他运行 python a.py 时,它实际上开始运行它(还有什么),但不会将其标记为已导入..因为它是正在执行的 __main__ 模块。 - gst

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接