Python 模块导入 - 为什么组件只有在显式导入时才可用?

Python module import - why are components only available when explicitly imported?

我最近安装了 scikit-image 版本 0.11.3。我正在使用 python 2.7.10。当我导入整个模块时,我无法访问 io 模块。

import skimage
img = skimage.io.imread(path_)

给出错误:

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

但是下面不报错

from skimage import io
img = io.imread(path_)

问题:为什么?

快速回答:IO 是一个子模块。需要从父模块显式导入子模块。

长答案:来自 python 文档的第 5.4.2 节:

当使用任何机制(例如 importlib API、import 或 import-from 语句,或内置 import())加载子模块时,绑定被放置在父模块的命名空间到子模块对象。例如,如果包 spam 有一个子模块 foo,在导入 spam.foo 之后,spam 将有一个属性 foo 绑定到子模块。假设您具有以下目录结构:

spam/
    __init__.py
    foo.py
    bar.py

and spam/init.py 中有以下几行:

from .foo import Foo
from .bar import Bar

然后执行以下命令将名称绑定到垃圾邮件模块中的 foo 和 bar:

>>>
>>> import spam
>>> spam.foo
<module 'spam.foo' from '/tmp/imports/spam/foo.py'>
>>> spam.bar
<module 'spam.bar' from '/tmp/imports/spam/bar.py'>

考虑到 Python 熟悉的名称绑定规则,这可能看起来令人惊讶,但这实际上是导入系统的一个基本特征。不变的持有是,如果你有 sys.modules['spam'] 和 sys.modules['spam.foo'] (就像你在上面导入之后一样),后者必须显示为 foo前者的属性。

这就是 Python 处理模块的方式。

一个原因是,如果 cpython 需要扫描子模块,导入所有子模块,然后再导入所有子模块,那么导入一个模块会非常慢。

另一个原因是"better be explicit than implicit"。当您只需要具有复杂模块层次结构的包的一小部分时,为什么要 Python 导入所有可能的东西。

代替from skimage import io你也可以写

import skimage.io

然后skimage.io.imread会被发现。