我在弄清楚如何在Python中进行相对导入时遇到了一些困难。我目前正在进行我的第一个主要项目,所以我想使用单元测试来正确地完成它。但是,我的文件结构和相对导入有问题。
这是我目前的结构:
App/
__init__.py
src/
__init__.py
person.py
tests/
__init__.py
person_tests.py
我想做的是能够将person.py导入到person_tests.py中进行单元测试。我尝试了以下操作:
from . import person
from .. import person
from .App.src import person
from ..App.src import person
from ..src.person import *
from ..src import person
from .src import person
以上每一个都会抛出语法错误或
ValueError: Attempted relative import in non-package
有人能帮我澄清一下吗?
编辑:Python版本为2.7。编辑:我希望能够将其与例如unittest或nose一起使用。
我的猜测(如果我错了,我会删除它)是,您正试图通过以下操作将person_tests.py
用作顶级脚本,而不是包内的模块:
$ cd App/tests
$ python person_tests.py
在这种情况下,person_tests
最终不会成为App.tests.person_tests
,而只是成为__main__
(或者,有一些细微的变化,成为具有相同基本问题的顶级person_tests
)。因此,..
并不引用App
,因此无法将person
作为相对导入。
更一般地说,PYTHONPATH
上的任何内容,包括.
,都不应该位于任何程序包目录的中间,否则就会损坏。
正确的答案是不要那样做。这样做:
$ python -m App.tests.person_tests
或者编写一个导入模块的顶级(包外)脚本,并运行该顶级脚本。
正如abarnert所说,您不能根据脚本的当前名称将脚本作为main进行相对导入。引用自文件:
请注意,显式和隐式相对导入都基于当前模块的名称。由于主模块的名称为始终为"__main__",打算用作Python应用程序应该始终使用绝对导入。
.
表示当前包,..
表示父包。所以你的一些重要声明是错误的。
from . import person # wrong for no person module in package tests
from .. import person # wrong for no person module in package app
from .App.src import person # wrong for no app package in package tests
from ..App.src import person # wrong for no app package in package app
from ..src.person import * # right
from ..src import person # right
from .src import person # wrong
相对进口的标准可以参考PEP328。
您可以将其附加到sys.path.
import sys
sys.path.append("../src")
import person