命名空间Python包(无__init__.py
)与常规Python包(具有__init__.py
)之间的区别是什么,特别是当__init__.py
为空时常规包装
我很好奇,因为最近我忘了在我制作的包中制作__init__.py
,我从来没有注意到任何问题。事实上,它们似乎与常规包装相同。
编辑:仅支持Python 3.3(see PEP 420)的命名空间包,所以很自然地,这个问题仅适用于Python 3.
答案 0 :(得分:10)
命名空间包是一种特殊的包,它允许您在Python路径的不同点统一两个具有相同名称的包。例如,将path1和path2视为Python路径上的单独条目:
path1
+--namespace
+--module1.py
+--module2.py
path2
+--namespace
+--module3.py
+--module4.py
通过这种安排,你应该能够做到以下几点:
from namespace import module1, module3
因此,您可以在单个命名空间中统一两个具有相同名称的包。如果其中任何一个__init__.py
成为 包,则您将无法再获得统一,因为其他目录将被忽略。
__init__.py
才能使目录成为包命名空间包是没有__init__.py
的包。
有关简单包的示例,如果您有一个目录:
root
+--package
+--file1.py
+--file2.py
...
虽然您可以在package
目录中单独运行这些文件,例如使用python file1.py
或python3 file1.py
,您将无法将文件作为模块导入根目录,例如。
import module.file1
会失败,为了让它起作用,你至少需要这个:
module
+--__init__.py
+--file1.py
+--file2.py
...
__init__.py
初始化软件包,您可以在首次导入模块时运行的__init__.py
中包含代码,
run_initial_import_setup()
提供要导入的__all__
名称列表
__all__ = ['star_import', 'only', 'these', 'names']
如果使用以下内容导入:
from module import *
或者如果您只想导入目录中剩余的.py文件,则可以将其保留为空,但这是要求能够执行此操作。
您最初可以使用自Python 2.3以来可用的pkgutil。通过将以下内容添加到每个单独的包__init__.py
:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
Setuptools使用类似的方法,同样,所有__init__.py
文件都应包含以下内容(没有其他代码):
import pkg_resources
pkg_resources.declare_namespace(__name__)
中更彻底地解决了命名空间问题
另请参阅此处有关setuptools和命名空间的更多讨论:
http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
答案 1 :(得分:3)
从Aaron和link阅读PEP420,看起来命名空间包和常规包之间的根本区别,除了常规包可能包含{{{{{{{ 1}},是一个名称空间包是一个虚拟包,其内容可以沿着Python的查找路径分布在不同的地方。
例如,给定
__init__.py
如果a/foo/bar.py
b/foo/baz.py
和b
都在Python的路径中,您可以自由导入a
和foo.bar
。
当然,这就引出了一个问题,即如果不需要foo.baz
,那么所有其他条件相同,那么制作常规包或命名空间包更好,但有点偏离主题。
答案 2 :(得分:-2)
__init__.py
成功,您可以将该软件包导入其他位置。 __init__.py
文件可以包含每次加载模块时要执行的代码。