本文介绍了Python中制作namespace包的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

From Namespace Packages in distribute, I know I can make use of namespace packages to separate a big Python package into several smaller ones. It is really awesome. The document also mentions:

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

__import__('pkg_resources').declare_namespace(__name__)

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

This code ensures that the namespace package machinery is operating and that the current package is registered as a namespace package.

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

I'm wondering are there any benefits to keep the same hierarchy of directories to the hierarchy of packages? Or, this is just the technical requirement of the namespace packages feature of distribute/setuptools?

例如,

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

I would like to provide a sub-package foo.bar, such that I have to build the following hierarchy of folders and prepare a __init__.py to make setup.py work the namespace package:

~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 中提供了这些信息?

I'm not familiar with namespace packages but it looks to me that 1) foo/bar and 2) (nearly) one-lined __init__.py are routine tasks. They do provide some hints of "this is a namespace package" but I think we already have that information in setup.py?

如下块所示,我的工作目录中是否可以有一个没有嵌套目录和单行 __init__.py 的命名空间包?也就是说,我们可以让 setup.py 只用一行 namespace_packages = ['foo'] 自动生成那些吗?

As illustrated in the following block, can I have a namespace package without that nested directory and one-lined __init__.py in my working directory? That is, can we ask setup.py to automatically generate those by just putting one line namespace_packages = ['foo']?

~foo.bar/
~foo.bar/setup.py
~foo.bar/src/__init__.py    <=    for bar package
~foo.bar/src/foobar.py

推荐答案

命名空间包主要在导入子包时有特殊作用.基本上,这是导入 foo.bar

A namespace package mainly has a particular effect when it comes time to import a sub-package. Basically, here's what happens, when importing foo.bar

  • 导入程序扫描 sys.path 寻找类似于 foo 的东西.
  • 当它找到某些东西时,它会在发现的 foo 中查找 bar.
  • 如果没有找到 bar:
  • the importer scans through sys.path looking for something that looks like foo.
  • when it finds something, it will look inside of the discovered foo for bar.
  • if bar is not found:
  1. 如果 foo 是一个普通的包,会引发 ImportError,表明 foo.bar 不存在.
  2. 如果 foo 是一个 namespace 包,导入器将返回通过 sys.path 查找 foo 的下一个匹配项.ImportError 仅在所有路径都用尽时才会引发.
  1. if foo is a normal package, an ImportError is raised, indicating that foo.bar doesn't exist.
  2. if foo is a namespace package, the importer goes back to looking through sys.path for the next match of foo. the ImportError is only raised if all paths have been exhausted.

这就是它所做的,但并没有解释你为什么想要那样.假设您设计了一个大而有用的库 (foo),但作为其中的一部分,您还开发了一个小而非常有用的实用程序 (foo.bar),其他 python 程序员发现有用,即使他们对更大的图书馆没有用处.

So that's what it does, but doesn't explain why you might want that. Suppose you designed a big, useful library (foo) but as part of that, you also developed a small, but very useful utility (foo.bar) that others python programmers find useful, even when they don't have a use for the bigger library.

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

You could distribute them together as one big blob of a package (as you designed it) even though most of the people using it only ever import the sub-module. Your users would find this terribly inconvenient because they'd have to download the whole thing (all 200MB of it!) even though they are only really interested in a 10 line utility class. If you have an open license, you'll probably find that several people end up forking it and now there are a half dozen diverging versions of your utility module.

您可以重写整个库,使实用程序位于 foo 命名空间之外(只是 bar 而不是 foo.bar).您将能够单独分发该实用程序,您的一些用户会很高兴,但这需要大量的工作,尤其是考虑到实际上 很多用户正在使用整个库,因此他们必须重写他们的程序才能使用新的.

You could rewrite your whole library so that the utility lives outside the foo namespace (just bar instead of foo.bar). You'll be able to distribute the utility separately, and some of your users will be happy, but that's a lot of work, especially considering that there actually are lots of users using the whole library, and so they'll have to rewrite their programs to use the new.

所以您真正想要的是一种自行安装 foo.bar 的方法,但在需要时也可以与 foo 愉快地共存.

So what you really want is a way to install foo.bar on its own, but happily coexist with foo when that's desired too.

命名空间包完全允许这样,foo 包的两个完全独立的安装可以共存.setuptools 将识别出这两个包被设计为彼此相邻并礼貌地移动文件夹/文件,使它们都在路径上并显示为 foo,一个包含 foo.bar,另一个包含 foo 的其余部分.

A namespace package allows exactly this, two totally independent installations of a foo package can coexist. setuptools will recognize that the two packages are designed to live next to each other and politely shift the folders/files in such a way that both are on the path and appear as foo, one containing foo.bar and the other containing the rest of foo.

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

You'll have two different setup.py scripts, one for each. foo/__init__.py in both packages have to indicate that they are namespace packages so the importer knows to continue regardless of which package is discovered first.

这篇关于Python中制作namespace包的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 10:44
查看更多