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

rsk*_*rsk 51 python namespaces module runtime

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

__import__('pkg_resources').declare_namespace(__name__)
Run Code Online (Sandbox Code Playgroud)

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

Nat*_*han 42

它归结为两件事:

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

  2. 从setup utils pkg_resources'文档中,declare_namespace()"声明虚线包名称是"命名空间包",其包含的包和模块可以分布在多个发行版中."

因此__import__('pkg_resources').declare_namespace(__name__)将'pkg_resources'包导入临时包并调用declare_namespace存储在该临时包中的函数(该__import__函数可能是使用而不是import语句,因此命名时不会留下额外的符号pkg_resources).如果该码是在my_namespace/__init__.py,则__name__my_namespace和该模块将包括在所述my_namespace命名空间包.

有关详细信息,请参阅安装工具文档

有关实现相同效果的旧机制的讨论,请参阅此问题.

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


Iva*_*nov 7

这是一种在Python中声明所谓的"命名空间包"的方法.

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

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

你希望人们能够做到

import your_project.plugins.plugin1
import your_project.plugins.plugin2
...
Run Code Online (Sandbox Code Playgroud)

如果您的目录结构完全如上所述,那就没问题了

your_project/
    __init__.py
    plugins/
        __init__.py
        plugin1.py
        plugin2.py
Run Code Online (Sandbox Code Playgroud)

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

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