Я пишу приложение на 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()
Это прекрасно работает, мне просто интересно, есть ли более идиоматический способ выполнить то, что мы делаем с этим кодом.
Обратите внимание, что я специально не хочу использовать яйца или точки расширения. Это не проект с открытым исходным кодом, и я не ожидаю, что будут "плагины". Смысл в том, чтобы упростить основной код приложения и избавить от необходимости изменять его каждый раз, когда добавляется новый командный модуль.
dir(__import__)
. Список должен быть списком имен для эмуляции "из импорта имен ...".
importlib
: stackoverflow.com/a/54956419/687896