Как найти все дочерние модули в Python?
-
06-09-2019 - |
Вопрос
Хотя в Python довольно тривиально импортировать "дочерний" модуль в другой модуль и перечислить его атрибуты, это становится немного сложнее, когда вы хотите импортировать ВСЕ дочерние модули.
Я создаю библиотеку инструментов для существующего 3D-приложения.Каждый инструмент имеет свой собственный пункт меню и подменю.Я бы хотел, чтобы инструмент отвечал за создание своих собственных меню, поскольку многие из них меняются в зависимости от контекста и шаблонов.Я бы хотел, чтобы мой базовый модуль мог находить все дочерние модули и проверять наличие create_menu()
функцию и вызовите ее, если она ее найдет.
Каков самый простой способ обнаружить все дочерние модули?
Решение
используя режиссер () и модуль imp
Другие советы
Я думаю, что лучший способ сделать такого рода плагины - это использовать entry_points
и тот API для их запроса.
Когда я был в некотором роде и только начинал программировать на 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]
Это небезопасный или "правильный" способ, но, тем не менее, возможно, он нам пригодится.Это очень старый код, поэтому, пожалуйста, не бейте меня.
Описанное выше решение обхода файловой системы для поиска подмодулей в порядке, если вы реализуете каждый плагин как модуль на основе файловой системы.
Более гибким способом было бы создать явный список плагинов в вашем основном модуле, и каждый плагин (будь то модуль, созданный файлом, динамически или даже экземпляр класса) явно добавлял бы себя в этот список.Возможно, с помощью функции registerPlugin.
Запомни:"явное лучше неявного" - это часть дзена python.
Вы можете попробовать 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)