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


88

我注意到我今天想解释的东西很奇怪。我不是100%不确定如何将其表达为一个问题,所以google是不可能的。由于某些奇怪的原因,日志记录模块无法访问模块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'>

谁能解释为什么会这样?

Answers:


119

在Python中,需要先导入模块,然后才能访问它们。import logging仅导入日志记录模块。碰巧这logging是一个带有子模块的软件包,但是那些子模块仍然不会自动加载。因此,您需要先显式导入,logging.handlers然后才能访问它。

如果您想知道为什么有时看起来不需要多余的导入:某些软件包在导入时会导入其子模块的某些或全部-只需在__init__.py文件中进行这些导入即可。在其他情况下,可能是您导入了其他内容,也导入了logging.handlers。导入哪个代码都没有关系;只要流程中的某些内容在您logging.handlers访问之前就导入了,它就会在那里。有时看起来像包的模块实际上不是一个与osand类似的模块os.pathos不是软件包,它只是导入正确的其他模块(适用于您的平台)并调用它path,以便您可以按进行访问os.path


4

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

如果您想让您的任何文件夹成为python软件包-它必须包含__init__.py文件,即使是空文件也可以!

正如托马斯所说,__init__.p如果需要,您可以在y中导入额外的模块!但是模块/软件包只有在导入后才能访问...

如果要从模块导入所有内容,可以使用

from logging import *

其余的您也可以像下面一样访问处理程序模块,

from logging import handlers
print dir(handlers)


5
请不要使用from module import *。这几乎总是一个错误。
Thomas Wouters 2010年

如果你想要的一切,在一个包被自动导入,在做这些进口初始化的.py,而不是设置初始化的.py和做“从包导入*”的地方。
Thomas Wouters 2010年

2
@Pete:因为它“污染”了导致歧义和冲突的标准名称空间。如果有的话import zipperzipper.open()您会确切知道我在打哪个电话。相反from zipper import *open()它是内置的open或zipper.open或其他内容。import zipper as z如果您厌倦了打字,则是更可取的选择zipper
msw

3
@Pete:这也是一个问题,因为您可能在不知不觉中覆盖了某些名称空间。我以前使用from的numpy import *原因是,除非您导入所有的numpy(在IMO方面这是可怕的设计缺陷),但是numpy却导入了许多对象,否则某些numpy函数将不起作用。我最终重写了许多功能(我相信副本就是其中一个...我太累了,无法检查)。现在,如果要使用numpy太多,以至于我无法忍受一遍又一遍地输入,我会将numpy导入为np。
chriscauley,2010年

2
@dustynachos,哪个numpy函数有该缺陷?
Winston Ewert

2

托马斯·沃特斯(Thomas Wouters)很好地回答了这个问题,但是,我只是在原始文档中找到答案后才发现这个问题。为此,我认为我希望对此加以补充,以期将来它能更接近搜索引擎的顶部。

为什么会出现错误:' AttributeError:module'module_name '没有属性' sub_module_name ',即使我的编辑器(例如Visual Code)自动完成了子模块名称,也是如此:

 import module_name
 module_name.sub_module_name(parameter)

回答

编辑器的自动完成是基于项目的文件结构,而不是基于Python行为。导入模块时,不会“自动”导入子模块。参考Python文档以获取有关在使用时如何“自动”导入子模块的详细信息

 import module_name

该答案的主要贡献是在尝试导入“模块”或“包”时添加了AttributeError

希望这对某人有帮助!


1

我最近面临着同样的奇怪情况。因此,我敢打赌您已经删除了一些第三方lib导入。这样就删除了包含from logging import handlersfrom logging import *提供的lib handlers。在其他脚本中,您曾经有过类似的东西import logging并且刚刚使用过,logging.handlers并且您认为这是一种像我一样工作的方式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.