Я пишу приложение на Python, которое принимает в качестве аргумента команду, например:
$ python myapp.py command1
Я хочу, чтобы приложение было расширяемым, то есть позволяло добавлять новые модули, реализующие новые команды, без необходимости изменения основного источника приложения. Дерево выглядит примерно так:
myapp/
__init__.py
commands/
__init__.py
command1.py
command2.py
foo.py
bar.py
Поэтому я хочу, чтобы приложение находило доступные командные модули во время выполнения и выполняло соответствующий.
Python определяет функцию __ import __ , которая принимает строку для имени модуля:
__ import __ (name, globals = None, localals = None, fromlist = (), level = 0)
Функция импортирует имя модуля, потенциально используя данные глобальные и локальные значения, чтобы определить, как интерпретировать имя в контексте пакета. Список from дает имена объектов или подмодулей, которые должны быть импортированы из модуля, заданного именем.
Источник: https://docs.python.org/3/library/functions.html#import
Так что сейчас у меня есть что-то вроде:
command = sys.argv[1]
try:
command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
# Display error message
command_module.run()
Это прекрасно работает, мне просто интересно, есть ли, возможно, более идиоматический способ выполнить то, что мы делаем с этим кодом.
Обратите внимание, что я специально не хочу использовать яйца или точки расширения. Это не проект с открытым исходным кодом, и я не ожидаю, что будут "плагины". Смысл в том, чтобы упростить основной код приложения и избавить от необходимости изменять его при каждом добавлении нового командного модуля.