首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Python中创建命名空间包?

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

Stack Overflow用户
提问于 2009-11-05 02:27:10
回答 5查看 68.5K关注 0票数 150

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

代码语言:javascript
复制
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产品可以在该名称空间中定义模块?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-12-21 10:44:44

TL;DR:

在Python3.3上,你不需要做任何事情,只要不把任何__init__.py放在你的命名空间包目录中,它就会工作。在3.3之前的版本中,选择pkgutil.extend_path()解决方案而不是pkg_resources.declare_namespace()解决方案,因为它是面向未来的,并且已经与隐式名称空间包兼容。

Python3.3引入了隐式名称空间包,请参阅PEP 420

这意味着现在有三种类型的对象可以由import foo创建

  • foo.py file
  • 表示的模块常规包,由包含__init__.py file
  • A命名空间包的目录foo表示,由一个或多个目录<代码>D14表示,但不包含任何<代码>D15文件<代码>H216<代码>F217

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

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

模块和常规包将__file__设置为创建它们时所用的.py文件。常规和命名空间包都将__path__设置为创建它们的一个或多个目录。

当您执行import foo.bar时,上述搜索将首先搜索foo,然后如果找到包,则使用foo.__path__而不是sys.path作为搜索路径来搜索bar。如果找到foo.bar,则创建并初始化foofoo.bar

那么,常规包和名称空间包是如何混合的呢?通常不需要,但是旧的pkgutil显式名称空间包方法已经扩展到包括隐式名称空间包。

如果您有一个现有的常规包,它的__init__.py如下:

代码语言:javascript
复制
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)

..。传统行为是将搜索路径上的任何其他常规包添加到其__path__中。但在Python3.3中,它还添加了名称空间包。

因此,您可以使用以下目录结构:

代码语言:javascript
复制
├── path1
│   └── package
│       ├── __init__.py
│       └── foo.py
├── path2
│   └── package
│       └── bar.py
└── path3
    └── package
        ├── __init__.py
        └── baz.py

..。只要这两个__init__.pyextend_path行(并且path1path2path3在您的sys.path中),import package.fooimport package.barimport package.baz都可以工作。

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

票数 89
EN

Stack Overflow用户

发布于 2009-11-05 03:32:17

有一个名为pkgutil的标准模块,您可以使用它将模块‘附加’到给定的命名空间。

使用您提供的目录结构:

代码语言:javascript
复制
Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py

您应该将这两行放在Package-1/namespace/__init__.pyPackage-2/namespace/__init__.py (*)中:

代码语言:javascript
复制
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)

(*由于-unless声明了它们之间的依赖关系-您不知道它们中的哪一个将首先被识别-有关更多信息,请参阅PEP 420 )

正如documentation所说:

这会将以软件包命名的sys.path目录的所有子目录添加到软件包的__path__中。

从现在开始,您应该能够独立分发这两个包。

票数 81
EN

Stack Overflow用户

发布于 2009-11-05 03:33:52

This section should be pretty self-explanatory.

简而言之,将名称空间代码放在__init__.py中,更新setup.py以声明名称空间,您就可以自由使用了。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1675734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档