命名空间与常规包

时间:2014-02-17 02:18:40

标签: python python-3.x package

命名空间Python包(无__init__.py)与常规Python包(具有__init__.py)之间的区别是什么,特别是当__init__.py为空时常规包装

我很好奇,因为最近我忘了在我制作的包中制作__init__.py,我从来没有注意到任何问题。事实上,它们似乎与常规包装相同。

编辑:仅支持Python 3.3(see PEP 420)的命名空间包,所以很自然地,这个问题仅适用于Python 3.

3 个答案:

答案 0 :(得分:10)

命名空间包

命名空间包是一种特殊的包,它允许您在Py​​thon路径的不同点统一两个具有相同名称的包。例如,将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.pypython3 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__)

PEP 420

中更彻底地解决了命名空间问题

另请参阅此处有关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的路径中,您可以自由导入afoo.bar

当然,这就引出了一个问题,即如果不需要foo.baz,那么所有其他条件相同,那么制作常规包或命名空间包更好,但有点偏离主题。

答案 2 :(得分:-2)

  1. __init__.py成功,您可以将该软件包导入其他位置。
  2. 此外,__init__.py文件可以包含每次加载模块时要执行的代码。