我试图遵循PEP 328,其目录结构如下:

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

在core_test.py中,我有以下import语句

from ..components.core import GameLoopEvents

然而,当我运行时,我得到以下错误:

tests$ python core_test.py 
Traceback (most recent call last):
  File "core_test.py", line 3, in <module>
    from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package

四处搜索,我发现“相对路径即使使用__init__.py也无法工作”和“从相对路径导入模块”,但它们都没有帮助。

这里有什么我遗漏的吗?


当前回答

这里有一种方法会惹恼所有人,但效果很好。在测试运行中:

ln -s ../components components

然后像往常一样导入组件。

其他回答

正如Paolo所说,我们有两种调用方法:

1) python -m tests.core_test
2) python tests/core_test.py

它们之间的一个区别是sys.path[0]字符串。由于在执行导入时解释将搜索sys.path,因此我们可以使用tests/core_test.py:

if __name__ == '__main__':
    import sys
    from pathlib import Path
    sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
    from components import core
    <other stuff>

之后,我们可以使用其他方法运行core_test.py:

cd tests
python core_test.py
python -m core_test
...

注意,仅测试了py36。

如果将当前目录附加到sys.path,则可以直接使用import components.core:

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

对我来说,只有这样才能奏效:我必须将package的值显式设置为父目录,并将父目录添加到sys.path

from os import path
import sys
if __package__ is None:
    sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
    __package__= "myparent"

from .subdir import something # the . can now be resolved

我现在可以直接用python myscript.py运行我的脚本。

如果您的项目结构如下所示:

   project
     |
     | --- module1
     |      |
     |      file1.py
     |
     |-----module2
     |     |
     |     file2.py

您将从file2.py中导入file1.py,您可以在file2.py中执行此操作:

import sys
sys.path.append('.')

import file2

我仍然不知道为什么和怎么做,但这对我有用。

您可以使用from pkg.components.core导入GameLoopEvents,例如,我使用pycharm,下面是我的项目结构图,我只是从根包导入,然后就可以了: