Python 3.5中的包导入失败

时间:2018-04-06 11:50:43

标签: python python-3.x import

我有以下文件夹结构:

/main
    main.py
    /io
        __init__.py
        foo.py

在Python 2.7中,我将在main.py中编写以下内容:

import io.foo

from io.foo import *
Python 3.5中的wheareas我收到导入错误:

Traceback (most recent call last):
  File "./main.py", line 6, in <module>
    import io.foo
ImportError: No module named 'io.foo'; 'io' is not a package

到目前为止,我找不到任何帮助。

2 个答案:

答案 0 :(得分:6)

iobuilt-in module。不要将本地软件包命名为内置模块。

答案 1 :(得分:2)

虽然@ErikCederstrand的答案是正确的,可能对你来说已经足够了,但我很好奇为什么它失败了所以我开始挖掘cpython的来源。所以对于未来的访客来说,这就是我找到的。

失败的功能在于:https://github.com/python/cpython/blob/3.4/Lib/importlib/_bootstrap.py#L2207

在第2209行,它检查父模块是否已加载:

parent = name.rpartition('.')[0]  #  Value of 'io'

由于它已加载内置 io模块,因此它会继续正常运行。在if返回false之后,它继续分配父模块,该模块再次设置为“io”:

if name in sys.modules:
    return sys.modules[name]
parent_module = sys.modules[parent]

下一行是造成失败的原因,这是因为内置模块(无论如何io)没有__path__实例变量。你在这里看到的例外最终是你在运行它时所看到的:

try:
    path = parent_module.__path__
except AttributeError:
    msg = (_ERR_MSG + '; {!r} is not a package').format(name, parent)
    raise ImportError(msg, name=name)

如果您像Erik所说的那样更改模块名称,然后逐步完成整个过程,您可以看到调用获取parent_module .__ path__就像它应该的那样工作并且一切都很开心。

所以,tldr:你已经欺骗了导入系统,认为它已经加载了你的自定义模块,但是当它尝试像自定义模块那样使用它时会失败,因为它实际上是内置的io。 / p>

编辑:在__path__进行正常导入过程后,init_module_attrs似乎已在此设置:

 if _override or getattr(module, '__path__', None) is None:
     if spec.submodule_search_locations is not None:
         try:
             module.__path__ = spec.submodule_search_locations
         except AttributeError:
             pass