Python中从文件夹与包导入模块的区别及输出差异解析
普通目录与Python包的区别及输出差异解析
一、核心区别:命名空间包 vs 常规包
Python 3.3之后引入了命名空间包的特性,这就是你看到“没有__init__.py也能导入目录下模块”的原因,它和传统的常规包(带__init__.py)的核心区别如下:
- 存在形式:
- 常规包:必须有
__init__.py文件,这个文件就是包本身的模块载体。 - 命名空间包:不需要任何特殊文件,只是Python为了组织跨路径模块而创建的虚拟命名空间容器。
- 常规包:必须有
- 加载逻辑:
- 常规包:导入时会执行
__init__.py里的所有代码,你可以在这里定义包级变量、统一导入子模块、控制对外暴露的接口(比如用__all__)。 - 命名空间包:导入时不会执行任何代码,它唯一的作用就是让你能用
folder1.b这种层级结构访问子模块,本身没有实际的代码逻辑。
- 常规包:导入时会执行
二、你的输出差异到底是什么意思
无__init__.py时的输出
20 <module 'folder1' (namespace)> <module 'folder1.b' from '/path/to/study_import/folder1/b.py'>
这里的folder1是命名空间模块,标记(namespace)说明它只是个空的命名空间容器,没有对应的.py文件,Python创建它只是为了让你能通过层级路径访问子模块b。
添加__init__.py后的输出
20 <module 'folder1' from '/path/to/study_import/folder1/__init__.py'> <module 'folder1.b' from '/path/to/study_import/folder1/b.py'>
此时folder1变成了常规包模块,它直接对应你创建的__init__.py文件,Python导入包时会执行这个文件里的代码,所以输出明确显示了它的来源是__init__.py。你可以在这个文件里做很多事情,比如:
# folder1/__init__.py # 统一导入子模块的变量,让用户直接import folder1就能用VAR2 from .b import VAR2 # 控制from folder1 import *时能导入的内容 __all__ = ['VAR2']
三、其他值得注意的差异
- 包级功能:常规包可以通过
__init__.py实现包级别的配置、初始化逻辑,而命名空间包做不到,因为它没有可执行的文件。 - 兼容性:命名空间包是Python 3.3+才支持的特性,如果要兼容Python 2.x,必须使用带
__init__.py的常规包。
内容的提问来源于stack exchange,提问作者User051209
相关产品推荐
相关产品推荐

