Python 中的相对导入

Posted

技术标签:

【中文标题】Python 中的相对导入【英文标题】:Relative imports in Python 【发布时间】:2011-05-09 16:47:11 【问题描述】:

大家好——我正在使用 来拉扯我的头发。我已经在 SO 和其他论坛上阅读了 30 次文档和大量帖子 - 似乎仍然不起作用。

我的目录结构目前是这样的

src/
    __init__.py
    main.py
    components/
        __init__.py
        expander.py
        language_id.py
    utilities/
        __init__.py
        functions.py

我希望 expander.py 和 language_id.py 能够访问功能模块。我运行 python main.py,它可以通过 from components.expander import * 和 components.language_id import * 很好地访问模块。

但是,expander 和 language_id 里面的代码来访问功能模块:

from ..utilities.functions import *

我收到此错误:

ValueError: Attempted relative import beyond toplevel package

我已经检查了很多次,它似乎遵循文档。有人知道这里出了什么问题吗?

【问题讨论】:

您已经找到了解决方案,但要解释为什么需要它:包应该是完全独立的。当您在其中运行 main.py 时,它不会将 src/ 视为一个包。 【参考方案1】:

没关系,我解决了:

src/
    main.py
    mod/
        __init__.py
        components/
            __init__.py
            expander.py
            language_id.py
        utilities/
            __init__.py
            functions.py

main.py 然后将子包称为:

from mod.components.expander import *
from mod.utilities.functions import *

expander.py 和 language_id.py 可以通过以下方式访问 functions.py:

from ..utilities.functions import *

但有趣的是,我在 expander.py 使用的 components 目录中有一个文本文件。但是,在运行时它无法找到该文件,即使它位于同一目录中。我将文本文件移动到与 main.py 相同的目录并且它工作。似乎违反直觉。

【讨论】:

所有新模块导入的东西都坏了,不直观。 从您启动程序的工作目录中打开文本文件,而导入是相对于脚本的位置。您可以在模块中使用 __file__ 来查找其路径,从而引用同一目录中的内容,尽管它不是很优雅。如果文本文件是程序的静态数据,则将其制成 Python 模块并导入可能会更容易。 您可以使用pkgutil.get_data() (docs.python.org/library/pkgutil#pkgutil.get_data) 来检索文件,使用模块命名空间来定位它们。例如,raw_data = pkgutil.get_data('mod.components', 'data.txt') 将从文件中检索原始二进制数据。 对于那些仍然认为这个答案有效的人,这对我有用:sys.path.append(path) 解决方案是删除项目根目录中的 __init__ 文件。不需要创建一个新文件夹“mod”,

以上是关于Python 中的相对导入的主要内容,如果未能解决你的问题,请参考以下文章

详解Python中的相对导入和绝对导入

python中的绝对导入不起作用,相对导入起作用

python 2.5中的相对导入

Jupyter Notebook 中的 Python 相对导入

Python 中的相对导入

从 Python 中的相对路径导入