Я пишу приложение 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, locals = None, fromlist =(), level = 0)
Функция импортирует имя модуля, потенциально используя данные глобальные и локальные, чтобы определить, как интерпретировать имя в контексте пакета. В списке из списка указаны имена объектов или подмодулей, которые должны быть импортированы из модуля, указанного по имени.
Источник: 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()
Это работает отлично, мне просто интересно, возможно ли более идиоматический способ выполнить то, что мы делаем с этим кодом.
Обратите внимание, что я специально не хочу использовать яйца или точки расширения. Это не проект с открытым исходным кодом, и я не ожидаю, что там будут "плагины". Дело в том, чтобы упростить основной код приложения и удалить необходимость его изменения каждый раз при добавлении нового командного модуля.