如何导入Python命名空间包的所有子模块?

12

Python 命名空间包可以分布在多个目录、zip 文件或自定义导入器中。如何正确地遍历命名空间包的所有可导入子模块?


2
你想要达成什么目标?你已经尝试过什么了? - Daenyth
1
你可以使用pkgutil模块。https://dev59.com/0HA75IYBdhLWcg3wT3L8 - hostingutilities.com
我对将其用于插件枚举很感兴趣。 - joeforker
2个回答

2
这是一种我认为很好的方法。在命名空间中的一个包中创建一个名为all.py的新子模块。
如果你这样写:
import mynamespace.all

您将得到mynamespace模块的对象。该对象包含命名空间中加载的所有模块,无论它们在何处加载,因为只有一个mynamespace实例存在。

因此,在all.py中加载命名空间中的所有软件包即可!

# all.py

from pkgutil import iter_modules

# import this module's namespace (= parent) package
pkg = __import__(__package__)

# iterate all modules in pkg's paths,
# prefixing the returned module names with namespace-dot,
# and import the modules by name
for m in iter_modules(pkg.__path__, __package__ + '.'):
    __import__(m.name)

或者使用一行代码来保持all模块为空,如果你关心这种事情的话:

# all.py

(lambda: [__import__(_.name) for _ in __import__('pkgutil').iter_modules(__import__(__package__).__path__, __package__ + '.')])()  # noqa

从命名空间导入all模块后,您实际上会收到一个完全填充的命名空间模块:

import mynamespace.all

mynamespace.mymodule1  # works
mynamespace.mymodule2  # works
...

当然,如果您不想立即导入它们,您可以使用相同的机制枚举或处理命名空间中的模块。

0
请阅读导入混淆
它非常清楚地区分了导入包及其子模块的所有不同方式,并在此过程中回答了您的问题。当您需要从包中获取某个子模块时,编写from io.drivers import zip通常比编写import io.drivers.zip更方便,因为前者让您可以简单地引用模块而不是完整名称。 from modname import *,这提供了一种将模块中的所有项目导入当前命名空间的简便方法;但是,应该谨慎使用此语句。

我特别不是在问 "import *",当你从命名空间包中 "import *" 时,什么也不会发生。相反,我想遍历我可以导入的所有内容。 - joeforker
使用 * 导入是可怕的做法。虽然它在 Python 中是有效的,但除了少数特定情况外,它几乎总是一个坏主意。 - Daenyth
是的,我同意,因为它降低了时间效率,但在不知道要使用哪个特定模块的情况下,导入整个包就成为了救星。 - The Recruit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接