ZetCode

Python 相对导入

最后修改日期:2025年3月25日

Python 中的相对导入允许基于模块在包层次结构中相对于当前模块的位置来导入模块。它们使用点号表示法来指定此相对路径,并在 Python 包中广泛使用。本教程通过详细的示例来检查它们的语法、用法和实际应用。

相对导入在包开发中尤其有价值,可以提高可维护性并减少重组过程中的脆弱性。与定义从项目根目录开始的完整路径的绝对导入不同,相对导入指定相对于当前模块位置的路径。它们遵循 from .module import name 语法,其中点号指示包结构中的相对位置。

基本的相对导入语法

此示例说明了 Python 中相对导入的基本语法。

package_structure
mypackage/
├── __init__.py
├── module1.py
└── subpackage/
    ├── __init__.py
    └── module2.py

此目录布局表示一个名为 mypackage 的简单包。它包含一个顶层模块 module1.py 和一个子包 subpackage,其中包含自己的 module2.py__init__.py 文件将这些目录标记为 Python 包。

subpackage/module2.py
from ..module1 import function1

def function2():
    return function1() + " from module2"

module2.py 中,语句 from ..module1 import function1 执行相对导入。两个点号 (..) 指示 Python 上升一个包级别到父目录,从而访问 module1.py。然后,函数 function2 基于 function1 构建,并将一个字符串附加到其结果中。

from ..module1 import function1 语句是相对导入的一个例子。 双点表示向上移动一个包级别,从父包中的 module1.py 导入。相对导入需要包上下文,由 __init__.py 文件强制执行,并且不能在独立脚本中使用。

从父包导入

此示例演示了使用相对导入从父包导入。

package_structure
mypackage/
├── __init__.py
├── utils.py
└── subpackage/
    ├── __init__.py
    └── module.py

此结构定义了一个包 mypackage,其中顶层有一个实用程序模块 utils.py,以及一个包含 module.py 的子包 subpackage__init__.py 文件建立包层次结构。

subpackage/module.py
from ..utils import helper_function

def use_helper():
    return helper_function()

module.py 中,行 from ..utils import helper_function 从父包中的 utils.py 导入 helper_function。这两个点号指示 Python 上移一个级别,并且 use_helper 调用导入的函数。

from ..utils import helper_function 语句从父包中的 utils.py 检索 helper_function。双点表示在层次结构中上升一级。这种方法确保导入保持简洁,并且相对于当前模块,其来源清晰。

从同级模块导入

此示例演示了如何在同一包中从同级模块导入。

package_structure
mypackage/
├── __init__.py
├── module_a.py
└── module_b.py

此布局描述了一个包 mypackage,其中两个同级模块 module_a.pymodule_b.py 位于同一级别。__init__.py 文件将 mypackage 指定为包。

module_b.py
from .module_a import ClassA

class ClassB:
    def __init__(self):
        self.a = ClassA()

module_b.py 中,语句 from .module_a import ClassA 从同级模块 module_a.py 导入 ClassA。单点 (.) 指的是当前包,而 ClassB 在其构造函数中实例化 ClassA

from .module_a import ClassA 语句从同一包中的同级模块 module_a.py 访问 ClassA。单点表示当前包目录。此技术非常适合在同一级别的模块中组织相关功能。

多级相对导入

此示例说明了跨多个包级别的相对导入。

package_structure
mypackage/
├── __init__.py
├── module1.py
└── subpackage/
    ├── __init__.py
    ├── module2.py
    └── nested/
        ├── __init__.py
        └── module3.py

此结构概述了一个包 mypackage,其中包含一个顶层 module1.py 和一个子包 subpackage。 在 subpackage 中,有 module2.py 和一个嵌套的子包 nested,其中包含 module3.py。每个级别都有一个 __init__.py 文件。

nested/module3.py
from ...module1 import function1
from ..module2 import function2

def combined_function():
    return function1() + function2()

module3.py 中,行 from ...module1 import function1 使用三个点来上升两个级别,从 module1.py 导入 function1。语句 from ..module2 import function2 上移一个级别,从 module2.py 导入 function2combined_function 合并它们的输出。

from ...module1 import function1 语句向上导航两个包级别以到达 module1.py,而 from ..module2 import function2 上升一个级别到 module2.py。这展示了相对导入如何精确地处理复杂的层次结构。

__init__.py 中的相对导入

此示例演示了在包初始化文件中使用相对导入来塑造包的公共 API。

package_structure
mypackage/
├── __init__.py
├── core.py
└── utils/
    ├── __init__.py
    └── helpers.py

此层次结构定义了 mypackage,其中包含顶层 core.py 和一个子包 utils,其中包含 helpers.py__init__.py 文件建立包和子包结构。

utils/__init__.py
from .helpers import utility_function
from ..core import CoreClass

__all__ = ['utility_function', 'CoreClass']

utils/__init__.py 中,行 from .helpers import utility_function 从同一子包中的 helpers.py 导入 utility_function。语句 from ..core import CoreClass 向上到达父包,从 core.py 获取 CoreClass__all__ 列表定义了子包的公共接口。

__init__.py 文件采用相对导入来在包级别公开选定的项目。从 .helpers 导入的目标是同级模块,而 ..core 访问父包。此模式简化了对包 API 中关键组件的访问。

常见错误和解决方案

相对导入的最佳实践

来源

Python 相对导入文档

在本文中,我们探讨了 Python 相对导入,并通过实际示例演示了它们在包开发中的用法。

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我在编程教学方面拥有超过十年的经验。

列出所有 Python 教程