如何在Python中查找所有子模块?

时间:2009-05-26 18:25:16

标签: python module package python-import

虽然在Python中将“子”模块导入另一个模块并列出其属性是相当简单的,但是当您想要导入所有子模块时,它会变得稍微困难​​。

我正在为现有的3D应用程序构建工具库。每个工具都有自己的菜单项和子菜单。我希望该工具负责创建自己的菜单,因为许多菜单都会根据上下文和模板进行更改。我希望我的基本模块能够找到所有子模块并检查create_menu()函数,并在找到它时调用它。

发现所有子模块的最简单方法是什么?

6 个答案:

答案 0 :(得分:3)

我认为执行此类插件操作的最佳方法是使用entry_pointsAPI for querying them

答案 1 :(得分:1)

当我在Python中开始编程时,我已经为我的模块化IRC机器人编写了这个:


    # Load plugins

    _plugins = []

    def ifName(name):
        try:
            return re.match('([^_.].+)\.[^.]+', a).group(1)
        except:
            return None

    def isValidPlugin(obj):
        from common.base import PluginBase
        try:
            if obj.__base__ == PluginBase:
                return True
            else:
                return False
        except:
            return False

    plugin_names = set(ifilter(lambda a: a!=None, [ifName(a) for a in os.listdir(os.path.join(os.getcwd(), 'plugins'))]))
    for plugin_name in plugin_names:
        try:
            plugin = __import__('plugins.'+plugin_name, fromlist=['plugins'])
            valid_plugins = filter(lambda a: isValidPlugin(a), [plugin.__getattribute__(a) for a in dir(plugin)])
            _plugins.extend(valid_plugins)
        except Exception, e:
            logger.exception('Error loading plugin %s', plugin_name)

    # Run plugins

    _plugins = [klass() for klass in _plugins]

这不是安全或“正确”的方式,但也许我们会有用。这是非常旧代码所以请不要打败我。

答案 2 :(得分:1)

只要您将每个插件实现为基于文件系统的模块,上面遍历文件系统以查找子模块的解决方案就可以了。

更灵活的方式是在主模块中显式插件列表,并且每个插件(无论是由文件,动态创建的模块,甚至是类的实例)都会明确地将自己添加到该列表中。也许通过registerPlugin函数。

记住:“显式优于隐式”是python禅的一部分。

答案 3 :(得分:0)

使用dir()imp module

答案 4 :(得分:0)

pkgutil.walk_packages()似乎是正确的方法。这是我找到可用模块列表,然后导入其中一个模块的方法:

$ mkdir foo
$ touch foo/__init__.py
$ touch foo/bar.py
$ python
Python 3.8.2 (default, Jul 16 2020, 14:00:26) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
>>> from pkgutil import walk_packages
>>> list(walk_packages(foo.__path__))
[ModuleInfo(module_finder=FileFinder('/home/don/git/zero-play/zero_play/foo'), name='bar', ispkg=False)]
>>> from importlib import import_module
>>> bar = import_module('foo.bar')

答案 5 :(得分:-1)

您可以尝试glob bing目录:

import os
import glob

modules = glob.glob(os.path.join('/some/path/to/modules', '*.py'))

然后你可以尝试导入它们:

checked_modules
for module in modules:
    try:
        __import__(module, globals(), locals()) # returns module object
    except ImportError:
        pass
    else:
        checked_modules.append(module)