【问题标题】:How to write nested __init__.py files如何编写嵌套的 __init__.py 文件
【发布时间】:2021-02-19 20:01:49
【问题描述】:

我在编写的 Python 包中遇到嵌套的 __init__.py 问题。该包具有以下架构:

module/
├── __init__.py
├── submodule1
│   ├── __init__.py
│   └── source.py
└── submodule2
    ├── __init__.py
    ├── source.py
    └── subsubmodule2
        ├── __init__.py
        └── source.py

我的意图是能够访问在submodule2/source.pymodule.submodule2.functionsubsubmodules2/source.pymodule.submodule2.subsubmodule2.function 中定义的函数。

我尝试的第一件事是用这种方式在submodule2 中定义__init__.py

from .subsubmodule2 import *

但是这样做,我得到了在subsubmodules2/source.pymodule.submodule2.function(和module.function)中定义的函数。

如果我这样做:

from . import subsubmodule2

我通过module.subsubmodule2.function获得这些功能。

我还尝试在__init__ 中定义__all__ 关键字,但没有成功。如果我能很好地理解Python documentation,我想我可以留下空的__init__.py 文件并且它可以工作,但据我了解这也不是最佳做法。

按照我的模块的预期访问这些功能的最佳方式是什么?

【问题讨论】:

  • 也许你可以检查 PYTHONPATH 环境变量,这是 python 将找到模块的目录。默认情况下,这是您运行代码的地方。
  • 请说明你想要什么。正如您所描述的那样,__init__.py 没有定义任何东西——因此,没有“submodule2 中定义的函数”,只有“submodule2.sourcesubmodule2.subsubmodule2.source 中定义的函数”。您是在问如何将.source 中定义的对象拉到父模块中?
  • 感谢您指出歧义。我在文中澄清了,如果不清楚,很抱歉,但我显然是指“submodules2/source.py 中定义的函数等等。

标签: python python-3.x python-module


【解决方案1】:

module__init__.py文件中写入你要导入的模块

from . import submodule1
from . import submodule2
__all__ = ['submodule1', 'submodule2']

现在,在 submodule1 __init__.py 文件中写入

from . import source
from . import subsubmodule
# if you want to import functions from source then import them or in source.py
# define __all__ and add function which you want to expose
__all__ = ['souce', 'subsubmodule`]

现在在子模块__init__ 文件中定义要公开的函数或类

from . source import *
__all__ =  ['source']
# if you want to use * as import, i suggest you to use __all__ in source.py and mention all exposed function there

【讨论】:

  • 如果我这样做,在导入我的模块时,我会在 submodule1 上收到 ModuleNotFoundError 错误。我还缺少其他东西吗?
  • 尝试更改导入语句,如 from . import submodule1import submodule1import .submodule1 像这些语句,我只有这会导致问题
  • from . import <module> 是所有级别的正确陈述,谢谢!
  • 当我将主文件命名为 A.py 并有一个文件夹 A 时,我遇到了一个奇怪的情况。在我将其重命名为 B 文件夹后,它得到了修复。我想我必须写.A.A.A 已经与A.A 相同?身份证。想把它放在这里,可能会对某人有所帮助。它可能不引人注意。
  • @FLAW 使用文件夹名称,如果是 B,则使用 .B.A
【解决方案2】:

__init__.py 文件代表其各自的包。比如module/submodule2/__init__.py代表module. submodule2

为了将子模块中定义的对象拉入它们的包命名空间,导入它们:

# module/submodule2/__init__.py
from .source import *

由于__init__.py 是一个常规的Python 模块,我们也可以放弃一个单独的.source 模块,直接在__init__.py 中定义对象:

# module/submodule2/__init__.py

def function():
    ...

请注意,子 本身已经可以作为它们各自的名称使用。不必——事实上也不应该——将它们导入到父模块中。如果代码使用包导入它们,它们将被导入。

【讨论】:

  • 如果我不在submodule 中导入submodule,我在我的命名空间中看不到它。
  • 无论代码使用 submodule 应该导入它。这就是不在__init__.py 中导入它们的重点——因此它们仅在需要时导入。比较multiprocessing.queue module is missing until a Queue is instanced
  • 好的,经过测试我明白了。但是让我感到困扰的是,我倾向于使用__init__.py 来明确地公开我的 API,而且我还必须说,我发现它在交互式环境中的用户友好性要低得多(不可能“发现”给定的模块)。
猜你喜欢
  • 2021-07-10
  • 2010-12-29
  • 2020-11-20
  • 1970-01-01
  • 2020-07-20
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
相关资源
最近更新 更多