我的项目结构如下:
/project
main.py
/a_module
__init__.py
/sub_module
__init__.py
some_file.py
main.py
from a_module import main_api
a_module / __ init __。py
from sub_module import sub_api
sub_module / __ init __。py
from some_file import detail_api
在 a_module / __ init __。py 中,出现Unable to import 'sub_module'
错误。
为什么我不能导入'sub_module'
?
当我更改为相对路径时,解决错误。
from .sub_module import sub_api
但是我不明白,__init__.py
是否为公共设计了模块的API?为什么不将sub_module
视为模块而不是目录?对我来说这真是个糟糕的设计...
答案 0 :(得分:0)
__init__.py
在导入包含它的软件包时执行。但这不是你的问题。您的问题是,除非明确地是相对的,否则模块导入始终是绝对的。这意味着它们必须从sys.path
中的 some 目录链接。默认情况下,这包括工作目录,因此,当您从main.py
内部运行project
时,它可以找到a_module
,而找不到其他内容。
from sub_module import sub_api
在a_module/__init__.py
中的无效,因为导入始终是绝对的,除非明确地是相对的。因此导入显示为“从某个sys.path
根目录开始,找到一个名为sub_module
的顶级程序包,然后从其中导入sub_api
”。由于不存在这样的模块,因此会出现错误。 from .sub_module import sub_api
之所以有效,是因为您选择了相对导入,因此它不会从sys.path
开始。
有关为什么要执行此操作的示例,我将在默认法律绝对导入为法律({{1}启用Py3行为,这就是我们修复它的方法,但是尽管文档说了什么,但Py2从未默认启用它,唯一的默认行为是相对导入)。我们的布局是:
from __future__ import absolute_import
现在,我们天真地想起了嘿,我们将所有程序包放在一个共享的顶级命名空间下,并且子程序包涵盖其中的广泛类别,并且由于我们有许多其他的用于基础数学的实用程序,因此将它们放在 teamnamespace/
module.py
math/
mathrelatedsubmodule.py
othermathsubmodule.py
。问题是,对于像teamnamespace.math
这样的 non 数学模块,它们的工作时间是:
teamnamespace.module
它默认为相对查找,并将import math # or
from math import ceil
导入为teamnamespace.math
(完全无用的导入,因为它只是一个名称空间包,所有功能都在子模块中),而不是内置的-在math
模块中。实际上,如果没有Python 3行为,就没有合理的方法从math
下的模块中获取内置math
模块。鉴于Python 3的行为,您可以选择其中之一或两者(通过使用teamnamespace
来别名一个或另一个,而不会产生歧义:
as