从父文件夹子文件夹相对导入模块

51

假设有这样的目录结构

main/
    common/
        foo.py
    A/
        src/
            bar.py

我如何使用Python的相对导入bar中导入foo? 我已经通过将其添加到路径来找到了一个可行的解决方案,但这很丑陋。 在Python 2.7中有没有一种简单的方法可以使用单个import实现?

这是一个更复杂的问题的版本:

从父文件夹导入模块

3个回答

56

正确的相对导入应该是这样:

from ...common import foo

相对导入仅适用于一个包内部。如果main是一个包,那么可以在此处使用相对导入。如果main不是一个包,则不能使用。

因此,如果你正在运行位于/main/目录下的脚本,并执行类似import A.src.bar这样的操作,则该相对导入将会失败并提示"Attempted relative import beyond toplevel package"。这是因为相对导入试图导入顶层包A之外的内容。

但是,如果你正在运行位于/目录下的脚本,并执行类似import main.A.src.bar这样的操作,则该相对导入将会成功,因为main现在是一个包。在这种情况下,以下两者将是等效的:

from ...common import foo
from main.common import foo
为了回答你的评论: . 的意义不会因为脚本执行的位置而改变,它会根据包结构的不同而改变。

回答你的评论: . 的意思并不取决于脚本运行的位置,而是取决于包的结构。


13
那么,你说的第一个情况的解决方案是什么? - erfan mehraban

0
如果你正在使用遵循OPSEC实践的框架来限制脚本的顶级项目,但是你需要从其他地方导入一个本地库,而不是为每个脚本复制粘贴相同的库...(这就是我在这里的原因)你可以通过在包含代码的文件夹上创建一个符号链接来绕过这个问题。
以你的例子来说,可以这样做:
cd path2/A
ln -s path2/main/common common

然后你可以在bar.py中导入。
from A.common.foo import class

但是,如果你这样做,而不是在需要时创建__init__.py文件,那么我强烈反对。

你的回答可以通过提供更多支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的回答是否正确。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - undefined

0
为了使用相对导入,您必须拥有一个包。在这个例子中,我认为“主”文件夹是最佳的候选作为顶级包。在“main”文件夹中创建一个__init__.py并将以下代码放入其中,以使其成为包中的顶级文件夹:
__package__ = ''

现在你可以使用相对导入:
from ...common import foo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接