在Python中创建命名空间包的方法

Dra*_*uan 14 python setuptools module-packaging namespace-package

分布式的命名空间包中,我知道我可以利用命名空间包将一个大的Python包分成几个较小的包.真的很棒.该文件还提到:

顺便提一下,请注意,在正常的Python包布局中,项目的源树必须包含命名空间包'__init__.py文件(以及任何父包的__init__.py).这些__init__.py文件必须包含以下行:

__import__('pkg_resources').declare_namespace(__name__)
Run Code Online (Sandbox Code Playgroud)

此代码确保命名空间包机制正在运行,并且当前包已注册为命名空间包.

我想知道将相同的目录层次结构保存到包的层次结构有什么好处吗?或者,这只是distribute/setuptools的命名空间包功能的技术要求?

当然,

我想提供一个子包foo.bar,这样我就必须构建以下文件夹层次结构并准备__init__.py以使setup.py工作在命名空间包中:

~foo.bar/
~foo.bar/setup.py
~foo.bar/foo/__init__.py    <=    one-lined file dedicated to namespace packages
~foo.bar/foo/bar/__init__.py
~foo.bar/foo/bar/foobar.py
Run Code Online (Sandbox Code Playgroud)

我不熟悉命名空间包,但它在我看来1)foo/bar和2)(几乎)单行__init__.py是例行任务.它们提供了一些"这是命名空间包"的提示,但我认为我们已经在setup.py中有这些信息了?

编辑:

如下面的块所示,我可以在我的工作目录中使用没有该嵌套目录和单行__init__.py的命名空间包吗?也就是说,我们可以要求setup.py通过只放一行来自动生成它们namespace_packages = ['foo']吗?

~foo.bar/
~foo.bar/setup.py
~foo.bar/src/__init__.py    <=    for bar package
~foo.bar/src/foobar.py
Run Code Online (Sandbox Code Playgroud)

Sin*_*ion 43

在导入子包时,命名空间包主要具有特定的效果.基本上,这是导入时发生的情况foo.bar

  • 进口商通过sys.path寻找看起来像的东西进行扫描foo.
  • 当它找到的东西,它看起来的发现里面foobar.
  • 如果bar没有找到:
    1. 如果foo是普通包,ImportError则引发a,表示foo.bar不存在.
    2. 如果foo命名空间包,则导入器会返回查找sys.path下一个匹配项foo.在ImportError所有路径都已用尽,才会引发.

这就是它的作用,但并没有解释为什么你可能会这样做.假设你设计了一个很大的,有用的库(foo)但是作为其中的一部分,你还开发了一个小但非常有用的实用程序(foo.bar),其他python程序员发现它很有用,即使它们没有用于更大的库.

您可以将它们一起分发为一个包的大块(就像您设计的那样),即使大多数使用它的人只会导入子模块.你的用户会发现这非常不方便,因为他们必须下载整个东西(所有200MB!),即使他们真的只对10行实用程序类感兴趣.如果你有一个开放的许可证,你可能会发现有几个人最终要求它,现在你的实用程序模块有六个不同版本.

您可以重写整个库,以便实用程序位于foo命名空间之外(bar而不是foo.bar).您将能够单独分发该实用程序,并且您的一些用户会很高兴,但这是很多工作,特别是考虑到实际上很多用户使用整个库,因此他们将不得不重写他们的程序使用新的.

所以你真正想要的是一种独立安装的方式foo.bar,但是foo在需要的时候也很乐意共存.

命名空间包允许这两个完全独立的foo包安装可以共存. setuptools我们会认识到这两个软件包的设计是彼此相邻的,并且礼貌地移动文件夹/文件,使得它们都在路径上并显示为foo,一个包含foo.bar,另一个包含其余的foo.

你将有两个不同的setup.py脚本,每个脚本一个. foo/__init__.py在两个包中都必须指明它们是命名空间包,因此无论首先发现哪个包,导入器都知道继续.

  • 感谢分享.我更新了我的问题以明确说明:我的工作目录中是否有没有嵌套目录和单行__init__.py的命名空间包? (4认同)
  • 但是`foo`中的主库代码是不是需要在自己的子包中(比如`foo.core`,或者什么)?`foo`可以包含任何变量吗?请参阅http://stackoverflow.com/questions/14402112/namespace-packages-with-a-core-part (2认同)