所以,这是关于如何在包/子包中使用__init__.py的一组问题。我已经搜索过了,但惊讶地没有找到一个像样的答案。
如果我有以下结构(这只是一个明显简化的示例):
my_package/
__init__.py
module1.py
my_sub_package/
__init__.py
module2.py
module1.py的内容如下:
my_string = 'Hello'
module2.py的内容如下:
my_int = 42
第一个问题:如何默认导入包中的多个模块
__init__.py 文件应该包含什么内容?
我可以将它们留空,这种情况下 import my_package
实际上并没有做什么(很明显它会导入该包,但是该包实际上并不包含任何内容)。这通常是可以接受的,并且在大多数情况下应该发生。
但在这种情况下,我希望 import my_package
可以让我使用 my_package.module1.my_string
和 my_package.my_sub_package.module2.my_int
。
我可以在 my_package/__init__.py 中添加 __all__ = [ 'module1' ]
,在 my_package/my_sub_package/__init__.py 中添加 __all__ = [ 'module2' ]
,但我理解这只对使用通配符的导入语句有效(即只有 from my_package import *
和 from my_package.my_sub_package import *
)。
要实现这个功能,我可以这样做:
import my_package.module1
import my_package.my_sub_package
在 my_package/__init__.py 文件中
import my_package.my_sub_package.module2
我应该将代码放在my_package / my_sub_package / __init__.py中,但这是个好主意吗?当我在Python解释器(3.5.5)中执行此操作时,它会创建一个(看似)无限的my_package.my_package.my_package....序列。
一个相关但高度相关的问题:使用模块使文件保持合理大小
如果我想要能够进行以下操作
import my_package
print(my_package.my_string)
print(str(my_package.my_sub_package.my_int))
例如,如果我实际上有很多模块在每个包中(这在这个简单的示例中显然不适用,但可以轻松实现),我希望使用module1和module2仅将代码分离成更小、更易读的文件。
在my_package/__init__.py中执行from my_package.module1 import *
,在my_package/my_sub_package/__init__.py中执行from my_package.my_sub_package.module2 import *
,这样做是否合理?我不喜欢使用通配符导入,但是看起来导入一个模块中定义的所有内容并将它们列出来会使代码冗长。
第三个问题(也与此密切相关):避免在多个位置编写包名称
是否有一种方法可以在不将包名称放入源代码中的情况下实现上述目标?我之所以这样问,是因为我想避免在多个地方更改它的名称(在这个简单的示例中很容易通过IDE或脚本完成,但知道如何避免这种情况会很好)。
__init__.py
中使用星号导入并且通过黑客方式避免“不得不将包的名称放入源代码”是长期来看非常糟糕的想法——曾经历过这种情况,这是一个纯粹的维护噩梦。明确你从哪里导入和导入什么具有巨大的可读性和可维护性优势,并且实际上使重命名/重构更容易(因为你知道所有东西来自哪里)。 - bruno desthuilliers__init__.py + 子模块)并使用
init.py`作为你想要从子模块中公开的门面。 - bruno desthuilliers