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

这里有什么我遗漏的吗?


当前回答

如果有人在寻找变通办法,我偶然发现了一个。这里有一点上下文。我想测试我在文件中的一种方法。当我从内部运行时

if __name__ == "__main__":

它总是抱怨相对进口。我尝试应用上述解决方案,但失败了,因为有许多嵌套文件,每个文件都有多个导入。

这是我所做的。我刚刚创建了一个启动器,一个外部程序,可以导入必要的方法并调用它们。尽管这不是一个很好的解决方案,但它还是有效的。

其他回答

旧线程。我发现在__init__.py文件,然后在目标中使用from<CURRENT_MODULE>import*即可。

这取决于您希望如何启动脚本。

如果您想以经典的方式从命令行启动UnitTest,即:

python tests/core_test.py

然后,因为在这种情况下,“components”和“tests”是同级文件夹,所以可以使用sys.path模块的insert或append方法导入相关模块。类似于:

import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents

否则,您可以使用“-m”参数启动脚本(请注意,在本例中,我们讨论的是一个包,因此您不能使用“.py”扩展名),即:

python -m pkg.tests.core_test

在这种情况下,您可以简单地使用相对导入:

from ..components.core import GameLoopEvents

您最终可以将这两种方法混合使用,这样无论如何调用脚本,脚本都能正常工作。例如:

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        from components.core import GameLoopEvents
    else:
        from ..components.core import GameLoopEvents

因为您的代码包含if __name__==“__main__”,而该代码不能作为包导入,所以最好使用sys.path.append()来解决问题。

详细阐述伊格纳西奥·巴斯克斯·阿布拉姆斯的回答:

Python导入机制相对于当前文件的__name__工作。当您直接执行文件时,它没有通常的名称,而是使用“__main__”作为其名称。因此相对进口不起作用。

正如Igancio所建议的,您可以使用-m选项执行它。如果您的包中有一部分要作为脚本运行,那么还可以使用__package__属性告诉该文件在包层次结构中应该具有什么名称。

看见http://www.python.org/dev/peps/pep-0366/详细信息。

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