命名空间包pep-420是一种特殊的包,用于解决超大模型分布式开发和分发的问题.一言以蔽之,命名空间包是用于管理多个模块的一种方式.
命名空间包与普通包的区别在于
- 命名空间包没有
__init__.py
文件 - 作为模块导入会没有
__file__
属性
命名空间包在使用上和普通的模块没有什么不同,只是命名空间包加载的慢些.
在Python 3.2之前命名空间包并不合法,所有的模块文件夹中必须包含__init__.py
文件,而命名空间包的出现让没有__init__.py
文件的文件夹也可以成为模块,这还是有点颠覆性的.因此在本部分最开始对python模块的定义其实是不准确的.
利用命名空间包这个技术,配合对sys.path
的修改可以用来导入目录分散的代码.
比如有如下的目录树:
├── p1
│ └── demo
│ └── foo
│ └── __init__.py
└── p2
└── demo
└── bar
└── __init__.py
我们可以用如下方式将其导入.
import sys
sys.path.extend(['p1', 'p2'])
import demo
import demo.foo as foo
import demo.bar as bar
foo.who_i_am()
foo
bar.who_i_am()
bar
demo
<module 'demo' (<_frozen_importlib_external._NamespaceLoader object at 0x7fba604afa90>)>
foo
<module 'demo.foo' from '/Users/mac/WORKSPACE/GITHUB/BLOG/TutorialForPython/src/语法篇/模块/p1/demo/foo/__init__.py'>
可以看到foo
和bar
都被正常导入了,且被归并到了同一个父包demo
下.我们就可以说demo是一个命名空间包.foo
和bar
本身都有__init__.py
,他们本身都是普通包.
通常我们不太会写多层嵌套的命名空间包,毕竟扁平胜于嵌套.