gpt4 book ai didi

python - 如何在 Python 中创建命名空间包?

转载 作者:IT老高 更新时间:2023-10-28 12:32:48 28 4
gpt4 key购买 nike

在 Python 中,命名空间包允许您在多个项目之间传播 Python 代码。当您想要将相关库作为单独的下载发布时,这很有用。例如,使用 PYTHONPATH 中的目录 Package-1Package-2

Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py

最终用户可以import namespace.module1import namespace.module2

定义一个命名空间包的最佳方式是什么,以便多个 Python 产品可以在该命名空间中定义模块?

最佳答案

TL;DR:

在 Python 3.3 上,您无需执行任何操作,只需不要将任何 __init__.py 放入您的命名空间包目录中,它就会正常工作。在 3.3 之前,选择 pkgutil.extend_path() 解决方案而不是 pkg_resources.declare_namespace() 解决方案,因为它是面向 future 的并且已经与隐式命名空间包兼容。


Python 3.3 引入了隐式命名空间包,见 PEP 420 .

这意味着现在可以通过 import foo 创建三种类型的对象:

  • foo.py 文件表示的模块
  • 一个常规包,由包含 __init__.py 文件的目录 foo 表示
  • 一个命名空间包,由一个或多个目录 foo 表示,没有任何 __init__.py 文件

包也是模块,但这里我说的“模块”是指“非包模块”。

首先它会扫描 sys.path 以查找模块或常规包。如果成功,它将停止搜索并创建和初始化模块或包。如果它没有找到模块或常规包,但它至少找到一个目录,它会创建并初始化一个命名空间包。

模块和常规包将 __file__ 设置为创建它们的 .py 文件。常规和命名空间包的 __path__设置为创建它们的目录。

当你执行 import foo.bar 时,上面的搜索首先发生在 foo,然后如果找到一个包,则搜索 bar 使用 foo.__path__ 作为搜索路径而不是 sys.path。如果找到 foo.bar,则创建并初始化 foofoo.bar

那么常规包和命名空间包是如何混合的呢?通常它们不会,但旧的 pkgutil 显式命名空间包方法已扩展为包含隐式命名空间包。

如果您有一个现有的常规包,其中包含这样的 __init__.py:

from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)

...遗留行为是将搜索到的路径上的任何其他常规包添加到其__path__。但在 Python 3.3 中,它还添加了命名空间包。

所以你可以有如下的目录结构:

├── path1
│   └── package
│   ├── __init__.py
│   └── foo.py
├── path2
│   └── package
│   └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py

...只要两个 __init__.pyextend_path 行(和 path1path2path3 在你的 sys.path) import package.foo, import package.barimport package.baz 一切正常。

pkg_resources.declare_namespace(__name__) 尚未更新为包含隐式命名空间包。

关于python - 如何在 Python 中创建命名空间包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1675734/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com