Aar*_*all 14
命名空间包是一种特殊的包,允许您在Python路径的不同点统一两个具有相同名称的包.例如,将path1和path2视为Python路径上的单独条目:
path1
+--namespace
+--module1.py
+--module2.py
path2
+--namespace
+--module3.py
+--module4.py
Run Code Online (Sandbox Code Playgroud)
通过这种安排,您应该能够执行以下操作:
from namespace import module1, module3
Run Code Online (Sandbox Code Playgroud)
因此,您可以在单个命名空间中统一两个具有相同名称的包.如果任何人有一个__init__.py变成了包-你不再得到统一为其他目录将被忽略.
__init__.py 曾经被要求使目录成为一个包命名空间包是没有的包__init__.py.
有关简单包的示例,如果您有一个目录:
root
+--package
+--file1.py
+--file2.py
...
Run Code Online (Sandbox Code Playgroud)
虽然您可以在package目录中独立运行这些文件,例如with python file1.py,或者python3 file1.py,您将无法将文件作为模块导入根目录,例如
import module.file1
Run Code Online (Sandbox Code Playgroud)
会失败,为了让它起作用,你至少需要这个:
module
+--__init__.py
+--file1.py
+--file2.py
...
Run Code Online (Sandbox Code Playgroud)
__init__.py初始化包,您可以在__init__.py首次导入模块时运行该代码,
run_initial_import_setup()
Run Code Online (Sandbox Code Playgroud)
提供__all__要导入的名称列表,
__all__ = ['star_import', 'only', 'these', 'names']
Run Code Online (Sandbox Code Playgroud)
如果使用以下内容导入:
from module import *
Run Code Online (Sandbox Code Playgroud)
或者,如果您只想导入目录中剩余的.py文件,则可以将其保留为空,但这是要求能够执行此操作.
您最初可以使用自Python 2.3以来可用的pkgutil.通过在每个单独的包中添加以下内容来完成添加命名空间__init__.py:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
Run Code Online (Sandbox Code Playgroud)
Setuptools使用类似的方法,同样,所有__init__.py文件应包含以下内容(没有其他代码):
import pkg_resources
pkg_resources.declare_namespace(__name__)
Run Code Online (Sandbox Code Playgroud)
在PEP 420中更彻底地解决了命名空间
另请参阅此处有关setuptools和命名空间的更多讨论:
http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
阅读Aaron 和PEP420的链接,似乎命名空间包和常规包之间的根本区别,除了常规包可能包含各种初始化代码的明显区别之外,命名空间包是一个虚拟包,其内容可以沿着Python的查找路径分布在各个地方。__init__.py
例如,给定
a/foo/bar.py
b/foo/baz.py
Run Code Online (Sandbox Code Playgroud)
如果 和b都a在Python的路径中,则可以自由导入foo.bar和foo.baz。
当然,这引出了一个问题,如果__init__.py不需要,那么在其他条件相同的情况下,制作常规包还是命名空间包更好,但这有点偏离主题。