Python3 包内的相对导入

Python3 Relative Imports inside a package

我意识到 Whosebug 上已经有很多关于此的问题,但我发现解决方案完全不清楚,而且经常相互矛盾。

我有以下场景:我正在编写一个具有以下结构的 python (Python 3.4) 包:

mypackage/
    __init__.py (empty file)
    mydir1/
        __init__.py (empty file)
        mymodule1.py
    mydir2/
        __init__.py (empty file)
        mymodule21.py
        mymodule22.py
    mydir3/
        __init__.py (empty file)
        mymodule31.py
        mymodule32.py
    tests/
        __init__.py (empty file)
        test_something_in_mydir1.py
        test_something_in_mydir2.py
        test_something_in_mydir3.py

我希望 tests/ 目录中的文件包含包内所有内容的单元测试。问题是无论我尝试哪种方法,我都会收到此错误:

SystemError: Parent module '' not loaded, cannot perform relative import

我应该注意,我希望它能工作 "out of the box" 这意味着我不想使用它们的绝对路径导入东西,我也不想更改我的路径变量。 None 这些解决方案看起来非常 pythonic,它让我慢慢地爬上墙。真的没有办法吗?

我已经尝试了很多东西,包括下面的示例,但它们似乎都产生了相同的结果:

from ..mydir1.mymodule1 import *
from .mypackage.mydir1.mymodule1 import *
from ...mypackage.mydir1.mymodule1 import *

并且我已经尝试覆盖每个 __init__.py 文件中的 __all__ 变量并进行导入,如下所示:https://docs.python.org/3/reference/import.html#submodules

谁能告诉我如何构建文件 test_something_in_mydir1.py 中的导入(例如),以便能够访问 [=37= 中找到的所有 classes/functions ] 对包进行单元测试?

如果test_something_in_mydir1.py包含:

import unittest
from ..mydir1 import mymodule1

class Test1(unittest.TestCase):
    def test1(self):
        self.assertEqual(mymodule1.x,1) # mymodule1 trivially contains x=1

并且如果使用以下命令从包含 包的目录 启动单元测试(在本例中为 C:\Test):

py -m unittest discover -v

发现测试并运行正确地使用相关导入:

C:\Test>tree /f
Folder PATH listing
Volume serial number is CE8B-D448
C:.
└───mypackage
    │   __init__.py
    │
    ├───mydir1
    │       mymodule1.py
    │       __init__.py
    │
    ├───mydir2
    │       mymodule21.py
    │       mymodule22.py
    │       __init__.py
    │
    ├───mydir3
    │       mymodule31.py
    │       mymodule32.py
    │       __init__.py
    │
    └───tests
            test_something_in_mydir1.py
            __init__.py


C:\Test>py -m unittest discover -v
test1 (mypackage.tests.test_something_in_mydir1.Test1) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK