为什么Python模块有时无法导入其子模块?

99

我今天注意到一些奇怪的事情,希望能够解释一下。我甚至不确定如何用问题来表达这个问题,因此谷歌是行不通的。出于某种奇怪的原因,logging模块无法访问logging.handlers模块。如果你不信,请自行尝试:

>>> import logging
>>> logging.handlers
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'handlers'
>>> import logging.handlers
>>> logging.handlers
<module 'logging.handlers' from '/usr/lib/python2.6/logging/handlers.pyc'>

有人可以解释一下为什么会发生这种情况吗?

4个回答

127

在Python中,模块需要在被使用前先导入。 import logging 仅导入日志模块。偶然的是,logging 是一个有子模块的包,但这些子模块并不会自动加载。因此,在访问它之前,您需要明确地导入 logging.handlers

如果您想知道为什么看起来有时您不需要那些额外的导入:一些包在其 __init__.py 文件中通过执行这些导入来导入一些或所有子模块。在其他情况下,可能是您导入的其他某些东西也导入了logging.handlers。无论哪一段代码进行导入都没有关系;只要您的进程中的 某个 导入了 logging.handlers,就会存在于其中。有时候,一个看起来像包的模块实际上并不是一个包,比如 osos.pathos 不是一个包,它只是导入正确的其他模块(对于您的平台)并将其命名为 path,以便您可以将其访问为 os.path


4

我也是Python的新手,经过大量练习后,现在我可以区分包(文件夹),模块(.py文件),类,变量等等...

如果你想要将你的任何文件夹作为Python包 - 它必须包含__init__.py文件,即使是空文件也可以!!!

正如Thomas所说,你可以在__init__.py中导入额外的模块,如果你想要的话!!!但是只有在导入之后才能访问模块/包...

如果你想从一个模块中导入所有内容,你可以使用

from logging import *

你可以像下面这样访问handlers模块:

from logging import handlers
print dir(handlers)


5
请勿使用 from module import *,这几乎总是错误的。 - Thomas Wouters
from module import *并不总是错误的,尽管99.9%的情况下至少对于内置模块来说是这样。有一些我使用的模块需要通配符导入,因为它们定义了许多需要使用的常量。 - Falmarri
2
@Pete: 因为它“污染”了标准命名空间,从而导致歧义和冲突。如果我有 import zipperzipper.open(),你会完全知道我调用的是哪个 open。相反,from zipper import * 后跟 open(),它是内置的 open 还是 zipper.open 还是其他什么。如果你厌倦了输入 zipper,则更喜欢使用 import zipper as z - msw
3
@Pete: 这也是一个问题,因为你可能会无意中覆盖一些命名空间。我曾经使用 from numpy import *,因为有些 numpy 函数只有在导入 numpy 的所有内容后才能使用(这是他们的糟糕设计缺陷,在我看来),但 numpy 导入了大量的对象。结果我不小心覆盖了很多函数(我相信其中一个是 copy……但我太累了,没法再去检查了)。现在如果我要经常使用 numpy,我会使用 import numpy as np,这样我就不用一遍又一遍地输入它的名称。 - chriscauley
2
@dustynachos,哪个numpy函数有这个缺陷? - Winston Ewert
显示剩余2条评论

3

Thomas Wouters在回答这个问题时做得非常好,但不幸的是,在找到原始文档中的答案之前,我才发现了这个问题。因此,我想添加一些内容,希望它能在未来更靠近搜索引擎的顶部。

问题

为什么会出现错误:'AttributeError: module 'module_name' has no attribute 'sub_module_name',即使我的编辑器(例如Visual Code)自动完成了子模块名称:

 import module_name
 module_name.sub_module_name(parameter)

答案

你的编辑器是基于项目文件结构而不是Python行为来提供自动补全功能的。导入模块时,子模块并不会被“自动”导入。参考Python文档,了解如何在使用时“自动”导入子模块。请注意保留HTML标记。
 import module_name

这个答案的关键贡献是在尝试导入“模块”或“包”时添加AttributeError。

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


1
我最近也遇到了同样奇怪的情况。所以,我猜你已经删除了一些第三方库的导入。那个被删除的库包含from logging import handlersfrom logging import *并为你提供了handlers。在其他脚本中,你可能会有类似于import logging的东西,并且只使用logging.handlers,就像我一样认为这是事情的方式。

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