Init Package Progress¶
(date: 2025-10-24)
怎样才能构成一个包 (原理)¶
在 Python 中,通常一个目录要被识别为一个包(package),需要在该目录中包含一个 __init__.py 文件。这个文件可以是空的,但它的存在是必要的,因为它告诉 Python 解释器这个目录是一个包。
不过,从 Python 3.3 开始,引入了一个新的特性,即“隐式命名空间包”(Implicit Namespace Packages)。这种类型的包不需要 __init__.py 文件,但有一些限制和要求:
目录结构:每个目录(包)必须包含一个
__init__.py文件,或者至少包含一个 Python 文件或子目录。PEP 420:Python 的 PEP 420 定义了命名空间包的规范,要求包目录必须包含
__init__.py文件,或者至少包含一个 Python 文件或子目录。
因此,如果你的子目录中不包含 __init__.py 文件,但包含至少一个 Python 文件或子目录,并且你使用的是 Python 3.3 或更高版本,那么这个子目录仍然可以被识别为一个包。
实验说明¶
这段笔记记录了一个关于Python模块导入机制的实验,主要目的是:
测试不同包结构的导入方式 - 包括常规包、子模块和命名空间包
验证导入路径和工作目录 - 通过
os.getcwd()检查当前工作目录演示命名空间包的特性 -
package3是一个空目录,形成了命名空间包
文件结构¶
module_test/
├── package1
│ ├── __init__.py
│ └── module1.py
├── package2
│ ├── __init__.py
│ └── module2.py
├── package3 # 空目录,形成命名空间包
└── script.py
module1.py¶
# module_test/package1/module1.py
import os
def run():
print("module 1 start ...")
print(os.getcwd())
print("module 1 end ...")
module2.py¶
# module_test/package2/module2.py
import os
def run():
print("module 2 start ...")
print(os.getcwd())
print("module 2 end ...")
script.py¶
# module_test/script.py
import os
print("script start ...")
print("Current working directory:", os.getcwd())
print("script end")
# 导入测试
from package1 import module1
from package2 import module2
import package3
# 执行导入的模块功能
module1.run()
module2.run()
# 显示package3的信息
print("package3 info:", package3)
print("package3 __path__:", getattr(package3, '__path__', 'No __path__'))
def run1():
print("run1 start ...")
print("Current working directory:", os.getcwd())
print("run1 end ...")
def run2():
print("run2 start ...")
print("Current working directory:", os.getcwd())
print("run2 end ...")
if __name__ == '__main__':
run1()
run2()
预期执行结果:¶
script start ...
Current working directory: /home/dai/PycharmProjects/module_test
script end
module 1 start ...
/home/dai/PycharmProjects/module_test
module 1 end ...
module 2 start ...
/home/dai/PycharmProjects/module_test
module 2 end ...
package3 info: <module 'package3' (namespace)>
package3 __path__: _NamespacePath(['/home/dai/PycharmProjects/module_test/package3'])
run1 start ...
Current working directory: /home/dai/PycharmProjects/module_test
run1 end ...
run2 start ...
Current working directory: /home/dai/PycharmProjects/module_test
run2 end ...
关键现象说明:¶
工作目录一致性:所有模块中的
os.getcwd()都显示相同的工作目录,即项目根目录命名空间包特性:
package3作为空目录(无__init__.py)被Python识别为命名空间包输出显示
<module 'package3' (namespace)>,表明这是一个命名空间模块命名空间包可以跨多个目录分布,为灵活的包结构提供支持
导入机制:
常规包(package1、package2)需要
__init__.py文件命名空间包(package3)不需要
__init__.py文件所有导入都成功执行,没有报错
这个实验清晰地展示了Python中不同包类型的导入行为和工作目录的保持一致性。