如何发现动态加载的模块

时间:2017-05-24 19:10:38

标签: python python-3.x

我试图使用importlib.util我最终只导入了importlib

$ python3.6
>>> import importlib
>>> importlib.util
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'importlib' has no attribute 'util'

因为我知道有importlib.util我然后导入了完整的模块名称

>>> import importlib.util
>>> importlib.util
<module 'importlib.util' from     '/Users/alexlord/.virtualenvs/python3.6/lib/python3.6/importlib/util.py'>

这看起来像一个动态模块,只有在您直接导入它时才会加载。

这让我感到惊讶,如何发现这些动态加载的模块?是否有一种编程方式来发现它们,或者我只需要枚举源代码?

1 个答案:

答案 0 :(得分:0)

默认情况下,包不会导入模块(或子包)。

所以:

import importlib

不会导入模块util。

但是开发人员可以选择为你做这件事。

例如:

>>> import os
>>> 
>>> os.path.pathsep
':'

要了解有关模块和包的所有信息,可以使用excellent tutorial

注意:您还可以使用“命名空间包”。有关详细信息,请参阅PEP 420

修改

要查找子模块,您可以使用pkg_resources.resource_listdir()

import pkg_resources

l = [m for m in pkg_resources.resource_listdir('importlib', '.')
     if m.endswith('.py') and not m.startswith('_')]

你得到:

['abc.py', 'machinery.py', 'util.py']

请参阅文档中的Basic Resource Access

编辑2

发现子包或子模块的另一种方法是使用pkgutil.walk_packages。这可能是最好的解决方案。

例如:

import pkgutil
import importlib

for i in pkgutil.walk_packages(importlib.__path__):
    print(i)

你得到:

(FileFinder('/var/containers/Bundle/Application/84CF9501-45D6-43E0-9319-886F5DE85176/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/importlib'), '_bootstrap', False)
(FileFinder('/var/containers/Bundle/Application/84CF9501-45D6-43E0-9319-886F5DE85176/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/importlib'), '_bootstrap_external', False)
(FileFinder('/var/containers/Bundle/Application/84CF9501-45D6-43E0-9319-886F5DE85176/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/importlib'), 'abc', False)
(FileFinder('/var/containers/Bundle/Application/84CF9501-45D6-43E0-9319-886F5DE85176/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/importlib'), 'machinery', False)
(FileFinder('/var/containers/Bundle/Application/84CF9501-45D6-43E0-9319-886F5DE85176/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/importlib'), 'util', False)