这里似乎已经有了一些关于python 3中相对导入的问题,但在浏览了许多之后,我仍然没有找到我的问题的答案。
问题来了。
我有一个如下所示的包
package/
__init__.py
A/
__init__.py
foo.py
test_A/
__init__.py
test.py
我在test.py中有一行:
from ..A import foo
现在,我在包的文件夹,我运行
python -m test_A.test
我收到消息
"ValueError: attempted relative import beyond top-level package"
但是如果我在包的父文件夹中,例如,我运行:
cd ..
python -m package.test_A.test
一切都很好。
现在我的问题是:
当我在包的文件夹中,我运行test_A子包中的模块作为test_A。测试,根据我的理解,..A只上升了一层,仍然在包文件夹中,为什么它给出消息说在顶层包之外。导致此错误消息的确切原因是什么?
我对这个问题的理解是这样的:
[案例1]当你开始一个绝对导入
python -m test_A.test
or
import test_A.test
or
from test_A import test
你实际上是将导入锚设置为test_A,换句话说,顶级包是test_A。当我们有test。py do from。一个导入xxx,你正在从锚转义,而Python不允许这样做。
[案例2]当你这样做的时候
python -m package.test_A.test
or
from package.test_A import test
你的锚变成了包,所以包/test_A/test.py从…导入xxx不会转义锚(仍然在包文件夹内),Python很乐意接受这一点。
简而言之:
Absolute-import改变当前锚(=重新定义什么是顶级包);
相对导入不会改变锚,而是限定在锚上。
此外,我们可以使用全限定模块名(FQMN)来检查这个问题。
检查每种情况下的FQMN:
【例2】测试。__name__ = package.test_A.test
(CASE1)测试。__name__ = test_A.test
对于CASE2, an。import xxx将生成一个带有FQMN=package的新模块。Xxx,这个可以接受。
对于CASE1, ..从内部从…import xxx将跳出test_A的起始节点(锚点),这是Python不允许的。
我认为这种“相对导入”的限制是一种相当丑陋的设计,完全违背了Python的格言“简单比复杂好”。
在python2中不确定。X,但在python 3.6中,假设你试图运行整个套件,你只需要使用-t
-t,——顶级-directory目录
项目的顶级目录(默认为开始目录)
在一个结构上
project_root
|
|----- my_module
| \
| \_____ my_class.py
|
\ tests
\___ test_my_func.py
例如,你可以用:
Python3 unittest discover -s /full_path/project_root/tests -t /full_path/project_root/
仍然导入my_module。My_class没有大的戏剧。