在模块的一些__init__.py
文件中,我看到了这样的单行:
__import__('pkg_resources').declare_namespace(__name__)
它做了什么以及为什么人们使用它?假设它与在运行时动态导入和创建命名空间有关。
答案 0 :(得分:39)
归结为两件事:
__import__
是一个Python函数,它将使用字符串作为包的名称导入包。它返回一个表示导入包的新对象。因此foo = __import__('bar')
将导入名为bar
的包,并将对象的引用存储在本地对象变量foo
中。
从setup utils pkg_resources'文档中,declare_namespace()
“声明[s]虚线包名称 name 是一个”命名空间包“,其包含的包和模块可能分布在多个发行版中。“
因此__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。