我试图遵循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也无法工作”和“从相对路径导入模块”,但它们都没有帮助。

这里有什么我遗漏的吗?


当前回答

如果您的用例是用于运行测试的,并且与之吻合,那么您可以执行以下操作。不要将测试脚本作为python core_test.py运行,而是使用诸如pytest之类的测试框架。然后在命令行上输入

$$ py.test

这将在您的目录中运行测试。这解决了@BrenBarn指出的__name__是__main__的问题。接下来,将一个空__init__.py文件放入测试目录,这将使测试目录成为包的一部分。那你就可以

from ..components.core import GameLoopEvents

然而,如果您将测试脚本作为主程序运行,那么事情将再次失败。所以只需要使用测试运行器。也许这也适用于其他测试者,比如鼻测试,但我没有检查过。希望这有帮助。

其他回答

这种方法对我有效,比一些解决方案更不杂乱:

try:
  from ..components.core import GameLoopEvents
except ValueError:
  from components.core import GameLoopEvents

父目录位于我的PYTHONPATH中,父目录和此目录中有__init__.py文件。

上面的方法在python 2中总是有效的,但是python 3有时会遇到ImportError或ModuleNotFoundError(后者在python 3.6中是新的,也是ImportError的一个子类),所以下面的调整对我在python 2和3中都有效:

try:
  from ..components.core import GameLoopEvents
except ( ValueError, ImportError):
  from components.core import GameLoopEvents

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

ln -s ../components components

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

在core_test.py中,执行以下操作:

import sys
sys.path.append('../components')
from core import GameLoopEvents

试试这个

import components
from components import *

对我来说,只有这样才能奏效:我必须将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运行我的脚本。