[英]The way to make namespace packages in Python
从分布式的命名空间包中 ,我知道我可以利用命名空间包将一个大的Python包分成几个较小的包。 真的很棒。 该文件还提到:
顺便提一下,请注意,在正常的Python包布局中,项目的源树必须包含命名空间包'__init__.py文件(以及任何父包的__init__.py)。 这些
__init__
.py文件必须包含以下行:__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
我不熟悉命名空间包,但它在我看来1)foo / bar和2)(几乎)单行__init__.py是例行任务。 它们确实提供了一些“这是命名空间包”的提示,但我认为我们已经在setup.py中提供了这些信息?
编辑:
如下面的块所示,我可以在我的工作目录中使用没有该嵌套目录和单行__init__.py的命名空间包吗? 也就是说,我们可以通过只设置一行namespace_packages = ['foo']
来请求setup.py自动生成这些吗?
~foo.bar/
~foo.bar/setup.py
~foo.bar/src/__init__.py <= for bar package
~foo.bar/src/foobar.py
在导入子包时,命名空间包主要具有特定的效果。 基本上,这是导入foo.bar
时发生的情况
sys.path
,查找看起来像foo
东西。 foo
里面的bar
。 bar
:
foo
是普通包,则会引发ImportError
,表明foo.bar
不存在。 foo
是命名空间包,则导入器会返回查看sys.path
以查找foo
的下一个匹配项。 只有在所有路径都已耗尽时才会引发ImportError
。 这就是它的作用 ,但并没有解释为什么你会这么想。 假设你设计了一个很大的,有用的库( foo
),但作为其中的一部分,你还开发了一个小但非常有用的实用程序( foo.bar
),其他python程序员发现它很有用,即使它们没有用于更大的图书馆
您可以将它们一起分发为一个包的大块(就像您设计的那样),即使大多数使用它的人只会导入子模块。 你的用户会发现这非常不方便,因为他们必须下载整个东西(所有200MB!),即使他们真的只对10行实用程序类感兴趣。 如果你有一个开放的许可证,你可能会发现有几个人最终要求它,现在你的实用程序模块有六个不同版本。
您可以重写整个库,以便实用程序位于foo
命名空间之外(只是bar
而不是foo.bar
)。 您将能够单独分发该实用程序,并且您的一些用户会很高兴,但这是很多工作,特别是考虑到实际上有很多用户使用整个库,因此他们将不得不重写他们的程序使用新的。
所以你真正想要的是一种foo.bar
安装foo.bar
的方法,但是当你想要的时候也很乐意与foo
共存。
命名空间包允许这两个完全独立的foo
包安装可以共存。 setuptools
会认识到这两个包被设计成彼此相邻并礼貌地移动文件夹/文件,使得它们都在路径上并显示为foo
,一个包含foo.bar
而另一个包含其余的foo
。
你将有两个不同的setup.py
脚本,每个脚本一个。 两个包中的foo/__init__.py
必须指示它们是命名空间包,因此无论首先发现哪个包,导入器都知道继续。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.