我有以下文件夹结构:
/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
到目前为止,我找不到任何帮助。
答案 0 :(得分:6)
io
是built-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