如何在 Python 中进行相对导入?

新手上路,请多包涵

想象一下这个目录结构:

 app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

我正在编码 mod1 ,我需要从 mod2 导入一些东西。我应该怎么做?

我尝试 from ..sub2 import mod2 但我收到“尝试在非包中进行相对导入”。

我四处搜索但只发现“ sys.path 操纵”黑客。没有一个干净的方法吗?


编辑:我所有的 __init__.py 目前都是空的

Edit2:我正在尝试这样做,因为 sub2 包含跨子包共享的类( sub1subX 等)。

Edit3:我正在寻找的行为与 PEP 366 中描述的相同(感谢 John B)

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

阅读 285
2 个回答

每个人似乎都想告诉你应该做什么,而不是仅仅回答问题。

问题是您通过将 mod1.py 作为参数传递给解释器来将模块作为“main”运行。

来自 PEP 328

相对导入使用模块的 name 属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,它被设置为’main‘),那么相对导入将被解析为就好像该模块是顶级模块一样,而不管该模块实际位于文件系统中的什么位置。

在 Python 2.6 中,他们添加了相对于主模块引用模块的能力。 PEP 366 描述了这一变化。

更新:根据 Nick Coghlan 的说法,推荐的替代方法是使用 -m 开关在包内运行模块。

原文由 John B 发布,翻译遵循 CC BY-SA 3.0 许可协议

这是对我有用的解决方案:

我将相对导入作为 from ..sub2 import mod2 然后,如果我想运行 mod1.py 然后我转到 app 的父目录并使用运行模块-- -m 切换为 python -m app.sub1.mod1

相对导入发生此问题的真正原因是,相对导入通过采用模块的 __name__ 属性来工作。如果模块直接运行,则 __name__ 设置为 __main__ 并且它不包含任何关于包结构的信息。而且,这就是 python 抱怨 relative import in non-package 错误的原因。

因此,通过使用 -m 开关,您可以向 python 提供包结构信息,通过它可以成功解析相关导入。

我在做相对导入时多次遇到这个问题。而且,在阅读了之前的所有答案之后,我仍然无法弄清楚如何以一种干净的方式解决它,而无需将样板代码放入所有文件中。 (虽然有些评论真的很有帮助,感谢@ncoghlan 和@XiongChiamiov)

希望这能帮助那些正在与相关进口问题作斗争的人,因为通过 PEP 真的不好玩。

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

推荐问题