ValueError:尝试相对导入超出顶级包

时间:2016-02-03 01:16:39

标签: python-3.x python-import

我正在玩Python的导入系统,以便更好地了解它是如何工作的,我遇到了另一个问题。我有以下结构

pkg/
    __init__.py
    c.py
    d.py

    subpkg/
        __init__.py
        a.py
        b.py

a.py内我有以下代码:

from . import b
from .. import d

c.py内,我有以下内容:

import subpkg.a

现在我收到以下错误:

  

ValueError:尝试相对导入超出顶级包

为什么?我该如何解决?我从IDLE运行c.pypkg应该被视为包,因为它有__init__.py文件。

第一个导入工作正常,但是以下不起作用:

from .. import d

因为我试图从父包中导入某些东西,但显然我不能,出于某种奇怪的原因。

5 个答案:

答案 0 :(得分:3)

Python 3更改了导入系统,因此每当您想要一个与您正在工作的模块相关的模块时,您需要相对导入(除非您弄乱PYTHON_PATHsys.path)。

此处的正确用法应为

from .subpkg import a

当您使用IDLE时,您将拥有完全不同的环境。因此,您可以将当前位置添加到路径中,以便再次导入。

尝试:

sys.path.insert(0, '')

这可能很奇怪,但这是为了更好的

PS:如果这最后一件事不起作用 - 我现在没有IDLE环境 - 可能是因为工作目录设置错误。

请尝试此答案:https://stackoverflow.com/a/17361545/754991

答案 1 :(得分:3)

这让我质疑我的精神错乱。

问题源于人们误以为误以相对进口作为相对的路径

相对导入取决于运行文件的位置。

answer更深入地解释了python模块的实际工作方式,但仅作总结。

  1. 在加载文件时,将为其指定一个名称:
    • 如果将其作为顶级脚本(直接运行)加载,其名称为__main__
    • 如果它是作为模块(带有导入)加载的,则其名称为文件名,其后是其一部分的所有软件包/子软件包的名称,并用点号-{{ 1}}
  2. 如果执行pkg.subpkg.a,则文件名中必须至少有2个点。 from ..-3个点。

现在是有趣的部分。

如果直接运行 c.py ,则其名称为from ...,而 a.py 具有__main__

根据第二条语句,您必须在subpkg.a的名称中至少有2个点才能在其中运行subpkg.a

修复

pkg 之外创建一个新文件,例如from ..

main.py

在main.py内部

pkg/
    __init__.py
    c.py
    d.py

    subpkg/
        __init__.py
        a.py
        b.py
main.py

如果我们运行 main.py ,它的名称为import pkg.c ,而 a.py 的名称为__main__。按照第二条语句,名称中现在有2个点,我们可以执行pkg.subpkg.a

还有一件事。现在 c.py 已作为模块加载,我们必须使用 from 加载 a.py

from ..

答案 2 :(得分:1)

我找到了这个解决方案:

#! /usr/bin/env python
import os
import sys
sys.path.append(os.path.realpath('.'))
from d import *

答案 3 :(得分:1)

只需在所有文件夹中添加/创建 init.py 文件即可解决问题。

文件夹 1 -文件夹2 -file1.py -文件夹3 -文件夹 4 - file2.py

我想使用 file2.py 中的 file1.py 中存在的方法 [基本上是两个级别]。 所以我在上面的所有文件夹和子文件夹中添加了空的 init.py,并在下面的 file2.py 中使用:-

从 folder2.file1 导入

答案 4 :(得分:0)

我对最佳答案表示感谢,但我发现提议的修复有点不令人满意。这是我的建议:只需将 sys.path.append(".") 添加到您的主文件中。这允许在不更改项目架构的情况下导入第一级包。只需删除之前不再需要的 .. 。