在 Python 中导入深度嵌套的模块

Posted

技术标签:

【中文标题】在 Python 中导入深度嵌套的模块【英文标题】:Importing deeply nested modules in Python 【发布时间】:2020-01-06 10:06:48 【问题描述】:

考虑 Python 3.6 中的以下情况:

basepackage
    |---__init__.py
    |---package
            |---__init__.py
            |---subpackage
                    |---__init__.py
                    |---module.py

重要细节:在basepackage.package.__init__.py里面有:

from basepackage.package.subpackage.module import AClass as AliasedClass

现在,假设在 basepackage.package.subpackage.module.py 内部我们要使用:

import basepackage.package.subpackage.module as aliased_module [1]

结果是:

AttributeError: module 'basepackage' has no attribute 'package'

在罪魁祸首语句之后列出堆栈跟踪(按以下顺序):

from basepackage.package.subpackage.module import AClass as AliasedClass
import basepackage.package.subpackage.module as aliased_module

但如果不是 [1] 想使用:

from basepackage.package.subpackage import module as aliased_module [2]

然后一切正常。

[1][2] 有何不同,以至于前者会导致错误,而后者不会?

【问题讨论】:

【参考方案1】:

要使第一个选项 (import basepackage.package.subpackage.module as aliased_module) 起作用,必须满足以下条件:

basepackage/__init__.py 必须包含类似于from . import package 的行(名称package 必须在此basepackage/__init__.py 文件中定义) basepackage/package/__init__.py 必须包含类似于 from . import subpackage 的行 basepackage/package/subpackage/__init__.py 必须包含类似于 from . import module 的行

注意:__init__.py 文件中的 import 语句也可以是绝对路径而不是相对路径。


对于第二个选项(from basepackage.package.subpackage import module as aliased_module),如果每个级别有空的__init__.py文件就足够了,只要这些__init__.py文件存在。

【讨论】:

谢谢。除了this section in the official docs 之外,您是否知道其他一些(更易于理解的)资源来了解这种行为? @z33k 也许这可以帮助realpython.com/python-modules-packages 与标准库有什么不同吗?因为我使用import xml.etree.ElementTree as ET 没有问题(注意ElementTree 是一个模块)并且我检查了源代码并且etree 包有一个空的__init__.py 并且在xml 的包中没有导入,只有@987654342 @ 已定义。 @z33k 嗯...也许我错了?我不知道,我很困惑,我不确定这个案子。在this part of the already linked tutorial 中,它似乎给出了一个与我在答案中的解释相反的例子。

以上是关于在 Python 中导入深度嵌套的模块的主要内容,如果未能解决你的问题,请参考以下文章

python如何删除已在shell中导入的模块?

在嵌套包中导入模块

python中pil如何导入?

python中导入模块/包的几种方式

在pycharm中导入自定义模块

python 中导入redis模块