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

新手上路,请多包涵

为了更好地了解它的工作原理,我在玩 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.py ,并且 pkg 应该被视为一个包,因为它有 __init__.py 文件。

第一次导入工作正常,但以下内容不起作用:

 from .. import d

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

原文由 nbro 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 433
1 个回答

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

问题源于人们 _错误地将相对导入作为路径相对的混淆,而实际上不是_。

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

这个 答案 更深入地解释了 python 模块的实际工作方式,但总结一下。

  1. 加载文件时,它会被赋予一个名称:
    • 如果它作为顶级脚本加载 (直接运行) ,它的名字是 __main__
    • 如果它作为模块加载 (使用导入) ,它的名称是文件名,前面是它所属的任何包/子包的名称,由点分隔 - pkg.subpkg.a
  2. 如果您执行 from .. 文件名中必须至少有 2 个点。 from ... - 3 个点。

现在是有趣的部分。

如果直接运行 c.py ,那么它的名称为 __main__a.py 的名称为 --- subpkg.a

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

修复

pkg 之外创建一个新文件,比如 main.py

 pkg/
    __init__.py
    c.py
    d.py

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

在 main.py 里面

import pkg.c

如果我们运行 main.py ,它得到的是名字 __main__ ,而 a.py 得到的是 pkg.subpkg.a 。根据第二条声明,它现在的名称中有 2 个点,我们可以执行 from ..

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

 from .subpkg import a

原文由 typhon04 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进