Python中命名空间包简介

Python 命名空间包是一种将多个独立包组合成单个可导入命名空间的方法。它们允许您拥有两个或多个可以在同一父命名空间下导入的单独包。

Python 命名空间包是一种高级 Python 特性。您可能听说过它们与 __init__.py 文件的关系。具体来说,如果您的包中没有包含至少一个空的 __init__.py 文件,那么您的包就会变成一个命名空间包。

在大多数情况下,命名空间包和普通包在项目中的使用行为并无不同。事实上,你可能不小心忘记在至少一个软件包中包含 __init__.py 文件,但却没有注意到任何副作用。虽然命名空间包的导入速度通常比普通包慢一些,但通常不会遇到太多问题。

Python 命名空间包可能会对管理或架构相关包集合的人有用。


命名空间软件包是什么样的?
假设你在ABC公司工作:

  • 你的团队希望确保其库中的所有软件包都能通过 abc_corp 命名空间访问。
  • 无论你使用什么软件包,只要它是由ABC公司制作的,你就可以从 abc_corp 导入。

如果没有命名空间软件包,你将有两种选择:

  1. 创建一个 monorepo,即一个名为 abc_corp 的单一软件包,其中包含数百个模块,可用于您可能需要的所有不同库和实用程序。
  2. 创建各种软件包,但都以 abc_corp 作为前缀。例如,你可以把 abc_corp _dateutil 作为一个软件包。

创建 monorepo 的麻烦在于,每个人都必须下载所有代码,即使他们只使用其中的一小部分。这也使版本管理和其他打包工作流程变得复杂,尤其是在不同团队负责不同子包的情况下。

命名空间包允许您拥有多个具有自己的打包工作流程的单独包,但它们都可以位于同一abc_corp 命名空间中。
现在将制作三个包:

  1. abc_corp-dateutil:一些特定于 ABC  Corporation 的日期实用程序
  2. abc_corp-magic-numbers:ABC Corporation 特有的一些数字生成实用程序
  3. abc-service:想要同时使用abc-corp-dateutil和abc-corp-magic-numbers包的员工项目

设置命名空间软件包
要开始设置 ABC 公司的命名空间软件包,请创建以下文件夹和文件结构:

abc-corp/

├── abc-corp-dateutil/
│   ├── abc_corp/
│   │   └── dateutil.py
│   └── pyproject.toml

├── abc-corp-magic-numbers/
│   ├── abc_corp/
│   │   └── magic.py
│   └── pyproject.toml

└── abc-service/
    └── abc_service.py

这样,你就拥有了三个软件包的基本文件结构。两个实用程序包(snake-corp-dateutil 和 snake-corp-magic-numbers)都首先定义了一个名为 abc_corp 的隐式命名空间包。之所以是隐式命名空间包,是因为没有 __init__.py 文件。

至于导入名称,

  • 导入 abc-corp-dateutil 包为abc_corp.dateutil,
  • 导入 abc-corp-magic-numbers 为 abc_corp.magic。

你将使用一个虚拟环境来容纳你的项目。在虚拟环境中,你将安装这两个实用程序包,这就是为什么你要为每个程序包都安装一个 pyproject.toml 文件的原因。这就模拟了在公司软件包服务器上安装这两个软件包的情况。


为什么需要命名空间包?
Python 命名空间包在两种情况下可能有用:

  1. 您有一个非常大的软件包,但并非该软件包的所有用户都需要访问它提供的所有内容。尽管如此,您还是想保留公共名称空间
  2. 您有许多不同且相关的包,并且您希望它们都共享相同的名称空间。

命名空间包可以提供更多用途,而不仅仅是将大量包分组在单个命名空间下。一个命名空间将它们全部包含进来,并在源代码中绑定它们!

潜在用例
当您想要将相关但独立的包合并到单个命名空间下以便于导入和组织时,命名空间包会很有用。

  • Python 标准库本身对某些组件使用命名空间包。
  • 它们还允许通过添加新的子包来扩展现有的命名空间,而无需修改原始包代码

尽管命名空间软件包并不常见--可能是因为大多数品牌命名空间软件包都是闭源的--但它们确实存在。下面是几个使用命名空间包的公共项目实例: