【问题标题】:Python module import - why are components only available when explicitly imported?Python 模块导入 - 为什么组件仅在显式导入时可用?
【发布时间】:2015-12-28 21:08:34
【问题描述】:

我最近安装了 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_)

问题:为什么?

【问题讨论】:

  • 考虑到像 os 这样的 stdlib 模块会自动将它们的子模块 (os.path) 拉入它们的命名空间,这尤其令人困惑。情况并不明显!

标签: python python-2.7 python-import


【解决方案1】:

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

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

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

spam/
    __init__.py
    foo.py
    bar.py

而 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 属性出现。

【讨论】:

    【解决方案2】:

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

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

    另一个原因是“比隐含更好”。当您只需要具有复杂模块层次结构的包的一小部分时,为什么 Python 应该导入所有可能的东西。

    除了from skimage import io,你也可以写

    import skimage.io
    

    然后会找到 skimage.io.imread。

    【讨论】:

    • 有点混乱。在过去的两周里,我一直在使用 import skimage 然后 skimage.io.imread,今天突然出现错误“AttributeError: ....has no attribute io”。我理解为什么显式导入子模块更有效但突然停止工作并没有多大意义。我的猜测是我昨天使用 pip 安装了一些软件包,它与之前安装的 skimage 版本冲突,现在它开始显示错误。
    猜你喜欢
    • 1970-01-01
    • 2012-03-07
    • 2011-01-25
    • 2015-09-29
    • 2014-01-09
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多