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

jms*_*usa 11 python python-import python-2.7

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

import skimage
img = skimage.io.imread(path_)
Run Code Online (Sandbox Code Playgroud)

给出错误:

AttributeError: 'module' object has no attribute 'io'
Run Code Online (Sandbox Code Playgroud)

但是以下不会出错.

from skimage import io
img = io.imread(path_)
Run Code Online (Sandbox Code Playgroud)

问题:为什么?

Sha*_*han 8

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

答案很长:从python文档的第5.4.2节开始:

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

spam/
    __init__.py
    foo.py
    bar.py
Run Code Online (Sandbox Code Playgroud)

和spam/init .py有以下几行:

from .foo import Foo
from .bar import Bar
Run Code Online (Sandbox Code Playgroud)

然后执行以下命令将名称绑定到垃圾邮件模块中的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'>
Run Code Online (Sandbox Code Playgroud)

鉴于Python熟悉的名称绑定规则,这似乎令人惊讶,但它实际上是导入系统的基本功能.不变量保持是如果你有sys.modules ['spam']和sys.modules ['spam.foo'](就像上面导入之后那样),后者必须显示为前者的foo属性.


cg9*_*909 6

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

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

另一个原因是“更好的是明确的而不是隐性的”。当您只需要一小部分具有复杂模块层次结构的软件包时,为什么Python应该尽可能地导入一切。

代替from skimage import io你也可以写

import skimage.io
Run Code Online (Sandbox Code Playgroud)

然后将找到skimage.io.imread。