Dra*_*uan 14 python setuptools module-packaging namespace-package
从分布式的命名空间包中,我知道我可以利用命名空间包将一个大的Python包分成几个较小的包.真的很棒.该文件还提到:
顺便提一下,请注意,在正常的Python包布局中,项目的源树必须包含命名空间包'__init__.py文件(以及任何父包的__init__.py).这些
__init__
.py文件必须包含以下行:Run Code Online (Sandbox Code Playgroud)__import__('pkg_resources').declare_namespace(__name__)
此代码确保命名空间包机制正在运行,并且当前包已注册为命名空间包.
我想知道将相同的目录层次结构保存到包的层次结构有什么好处吗?或者,这只是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
.foo
的bar
.bar
没有找到:
foo
是普通包,ImportError
则引发a,表示foo.bar
不存在.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
在两个包中都必须指明它们是命名空间包,因此无论首先发现哪个包,导入器都知道继续.