学习路线:B站
1.没有__init__文件时
目录结构:
├── moduleA.py
└── main.py
moduleA.py的内容如下:
print("moduleA is imported")
main.py内容如下:
import moduleA
运行main.py会打印输出如下:
moduleA is imported
2.导入一个package
目录结构如下:
├── packageA
└── moduleA.py
└── main.py
其中moduleA.py内容如下:
print("moduleA is imported")
main.py内容如下:
import packageA
运行main.py时,什么都不会打印。因为我们引入packageA并不会执行packageA中的moduleA.py,而是会执行一个__init__.py(目前我们还没有建立)。
3.重新导入package
目录结构如下:
├── packageA
├── __init__.py
└── moduleA.py
└── main.py
其中__init__.py内容如下:
print("packageA is imported")
其中moduleA.py内容如下:
print("moduleA is imported")
main.py内容如下:
import packageA
运行main.py时,可以看到执行了__init__.py,输出:
packageA is imported
说明我们导入一个package时,会自动执行这个package中的__init__.py文件。
注意这里没有输出
moduleA is imported说明,只是自动执行了__init__.py而不会自动执行moduleA.py
应该往__init__.py文件中放什么
- 包的初始化,有的包需要环境变量,有的包需要配置logging
- 包的公共接口,即包需要被外面使用的东西。
例如
moduleA.py内容如下:x = 'moduleA constant'
main.py内容如下:from packageA import x执行main.py会报错:ImportError: cannot import name ‘x’ from ‘packageA’
如果想要在
main.py中导入moduleA.py中的变量,需要再packageA中的__init__.py添加相对导入:from .moduleA import x这样就可以在main.py中执行x了
有时候我们会在main.py中导入packageA中的所有内容,例如main.py内容如下:
from packageA import *
print(x)
print(moduleA.x)
packageA中的__init__.py内容如下:
from . import moduleA # 默认就有这一行,最好写上这一行,逻辑更清晰一些
from .moduleA import x
__all__ = ['moduleA', 'x']
print("packageA is imported")
moduleA.py内容如下:
print("moduleA is imported")
x = 'moduleA constant'
运行main.py时,输出结果如下:
moduleA is imported
packageA is imported
moduleA constant
moduleA constant
总之:
__all__变量控制from package import *的行为
# 即使没有 __all__ 也可以访问
print(moduleA.模块A中的变量) # 可以正常输出(虽然能访问,但违反约定)
# 如果是通过 * 导入则无法访问
from packageA import *
print(moduleA中的变量) # NameError(如果 __init__.py 没有在 __all__ 中暴露)
- 当没有定义
__all__时,只会导入__init__.py中定义的名称 - 使用
__all__可以明确暴露的模块/变量(推荐始终显式定义)
注意区别 from packageA.moduleA import x与from packageA import x有什么区别:
from packageA.moduleA import x- 明确从 packageA 包的 moduleA 模块导入符号 x ** (会执行__init__.py中的代码,同时也会会执行moduleA中的代码)**
- 要求 moduleA 必须存在且包含 x 属性
- 导入路径: packageA → moduleA → x
from packageA import x- 尝试直接从 packageA 包的
__init__.py导入符号 x (只会执行__init__.py中的代码) - 需要
packageA/__init__.py中存在 x 定义或显式导入(例如 from .moduleA import x ) - 若
__init__.py未导出 x ,会引发 ImportError
- 尝试直接从 packageA 包的
- 包的信息,如作者、版本
# __init__.py
__version__ = "1.0.0"
__author__ = "Your Name"
__license__ = "MIT"
4. Python 3.3+ 的隐式命名空间包
从 Python 3.3 开始,即使没有 __init__.py 文件,目录也会被识别为包(称为 namespace package)。但显式创建 __init__.py 仍然是推荐做法:
- 支持传统包的明确初始化
- 更方便定义包级属性/方法
- 更好的IDE支持
4197

被折叠的 条评论
为什么被折叠?



