什么`__import __('pkg_resources')。declare_namespace(__ name __)`do?

时间:2011-10-16 17:15:31

标签: python module namespaces runtime

在模块的一些__init__.py文件中,我看到了这样的单行:

__import__('pkg_resources').declare_namespace(__name__)

它做了什么以及为什么人们使用它?假设它与在运行时动态导入和创建命名空间有关。

2 个答案:

答案 0 :(得分:39)

归结为两件事:

  1. __import__是一个Python函数,它将使用字符串作为包的名称导入包。它返回一个表示导入包的新对象。因此foo = __import__('bar')将导入名为bar的包,并将对象的引用存储在本地对象变量foo中。

  2. 从setup utils pkg_resources'文档中,declare_namespace()“声明[s]虚线包名称​​ name 是一个”命名空间包“,其包含的包和模块可能分布在多个发行版中。“

  3. 因此__import__('pkg_resources').declare_namespace(__name__)会将'pkg_resources'包导入临时包并调用存储在该临时包中的declare_namespace函数(可能使用__import__函数而不是import }语句,以便在命名pkg_resources)上没有剩余的符号。如果此代码位于my_namespace/__init__.py中,则__name__my_namespace,此模块将包含在my_namespace命名空间包中。

    有关详细信息,请参阅setup tools文档

    有关实现相同效果的旧机制的讨论,请参阅this question

    有关从Python 3.3开始提供类似功能的标准化机制,请参阅PEP 420

答案 1 :(得分:7)

这是一种声明所谓的"名称空间包"在Python中。

这些是什么,问题是什么:

想象一下,您发布的软件产品具有很多功能,而且并非所有人都想要所有功能,因此您将其拆分为多个部分并作为可选插件发布。

你希望人们能够做到

import your_project.plugins.plugin1
import your_project.plugins.plugin2
...

如果您的目录结构完全如上所述,那就没关系,即

your_project/
    __init__.py
    plugins/
        __init__.py
        plugin1.py
        plugin2.py

但是,如果将这两个插件作为单独的python包发送,那么它们位于两个不同的目录中呢? 然后您可能希望将__import__('pkg_resources').declare_namespace(__name__)放在每个包__init__.py中,以便Python知道这些包是更大的#34;命名空间包的一部分" ,在我们的例子中,your_project.plugins

有关详细信息,请参阅documentation