6

我在弄清楚如何在 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。 编辑:我希望能够将它与单元测试或鼻子一起使用。

4

3 回答 3

6

我的猜测(如果我错了,我会删除它)是您试图通过执行以下操作将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

或者编写一个导入模块的顶级(包外)脚本,然后运行该顶级脚本。

于 2013-08-05T23:12:00.557 回答
1

正如 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

于 2013-08-05T23:25:49.973 回答
-1

您可以将其附加到 sys.path。

import sys
sys.path.append("../src")
import person
于 2013-08-05T23:19:08.383 回答