我尝试按照PEP 328,使用以下目录结构︰

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

core_test.py中,我有以下的导入语句

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

围绕我搜索找到等处但回答这些问题中的甚至不接受我的工作。还有什么我忘记这里吗?

2012-07-18 07:59:14
问题评论:

我也是非常困惑的因此我写了此相当详尽的示例项目中涵盖的相对和绝对的导入的模块的深层嵌套结构unittest项目的各种方法 (在其中工作和不),和相对和绝对引用从在包中,以及单、 双,和包级导入的类。帮助清除我的事情就好

不能测试工作。当我运行它们会不断给no module named myimports.foo

我猜预期的调用 @Blairg23 是到cdPyImports,然后运行的python -m unittest tests.test_abs,例如。

回答:

是的。您没有使用它作为一个包。

python -m pkg.tests.core_test

隐患︰ 请注意,有没有.py 结尾处 !

我并不是 downvoters,但是我认为这可不少使用更多的细节,给出此问题和答案的普及。注意从哪个目录执行上面的 shell 命令,您需要一直向下__init__.pys 的事实和__package__类似的东西-修改诡计 (如下所述的 BrenBarn) 需要允许执行脚本的这些导入 (例如时使用 shebang 和执行在 Unix 外壳./my_script.py ) 就所有会很有用。这整个问题是我找出或上找到简洁易懂的文档非常棘手。

没有很好地阐述最近回答下面建议 upvoted 添加注释的文档的链接。

注意︰ 您需要在您调用 CLI 此行点目录pkg之外。然后,它应按预期方式工作。如果您位于pkg并调用python -m tests.core_test,它不起作用。至少它不适合我。

这不起作用如果您运行组件目录中的脚本为例

以 @Ignacio 的答案在详细阐述︰ python 导入机制相对于当前文件的__name__的工作原理。直接执行一个文件时,它没有它的常用名称,但有"__main__"作为它的名称改为。因此相对导入不起作用。您可以 Igancio 建议,作为执行它在使用-m 选项。如果您打算作为脚本运行的包的一部分,您可以使用__package__属性来告诉它本应包层次结构中有哪些名称的该文件。Http://www.python.org/dev/peps/pep-0366/的详细信息,请参阅。

用了一段时间我发觉无法运行python -m core_testtests子目录中-它必须是从父节点,或您需要添加到路径的父。

因此我因此可以使用来确保可执行脚本文件都可以相对导入来自无论其级别在层次结构中系统的其余部分?这是非常非常确实有用。

@DannyStaple︰ 不完全。您可以使用__package__以确保可执行脚本文件可以相对导入同一包中的其他模块。没有方法相对导入来源"整个系统"。我不确定甚至为什么要这样做。

我的意思是如果__package__符号设置为"parent.child",则您将无法导入"parent.other_child"。也许没有短语这项非常好。

@DannyStaple︰ 嗯,它的工作原理是文档中的描述链接。如果必须在包pack.subpack script.py脚本,然后将它的__package__设置为pack.subpack将允许您从执行from ..module import somethingpack.module中导入的内容。请注意,如文档指出,仍须在系统路径上具有顶级包。已导入模块的工作的方式。唯一件事__package__ does 是允许您使用直接执行脚本以及这种行为。

如果您可以使用import components.core直接到sys.path追加当前目录:

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

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))这还会起作用

一直下了答案绝对宝石 !大的 + 1 !

from os import sys看起来像:) 欺骗

@flyingsheep︰ 达成协议,我必须只使用常规import sys, os.path as path.

注意,ipython 笔记本电脑,在使用此我改编此答案︰import os; os.sys.path.append(os.path.dirname(os.path.abspath('.')))然后import components.core直工作对我来说,从笔记本的父目录,根据需要导入。

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

如果您希望向您 UnitTest 从命令行启动一种经典的方式,这就是︰

python tests/core_test.py

然后,因为在这种情况下,组件测试是同级文件夹,您可以导入相对模块使用插入附加sys.path模块的方法。类似这样的内容︰

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

应我如果做什么我将尝试使用用于调试 pdb?因为您可以使用python -m pdb myscript.py以启动调试会话。

@dannynjust-,是个好问题,因为不能有两个主要模块。通常在调试时,我更愿意放到想要开始调试的第一个点在手工调试程序。您可以import pdb; pdb.set_trace()插入的代码 (内联) 来完成该操作。

是更好一些,而不是append使用insert也就是说, sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

用例运行测试,并且其接缝,如果是,则您可以执行以下。而不是python core_test.py以运行您的测试脚本使用如pytest的测试框架。然后在命令行上可以输入

$$ py.test

它将在您的目录中运行测试。这避开了__name____main__的 @BrenBarn 指出,这一问题。接下来,放入测试目录的空__init__.py文件,这将使您的软件包的测试目录部分。然后您将能够执行操作

from ..components.core import GameLoopEvents

但是,如果作为主要程序运行您的测试脚本将再一次失败的事情。因此只需使用测试运行程序。也许这也适用于其他如nosetests的测试流道,但我还没有签。希望这能帮助。

请输入您的翻译

Attempted relative import in non-package even with __init__.py

确认取消