Как импортировать модуль по его имени в виде строки?

Я пишу приложение на 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)

Функция импортирует имя модуля, потенциально используя заданные глобальные и локальные значения, чтобы определить, как интерпретировать имя в контексте пакета. Список 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()

Это прекрасно работает, мне просто интересно, есть ли, возможно, более идиоматический способ выполнить то, что мы делаем с этим кодом.

Обратите внимание, что я специально не хочу использовать яйца или точки расширения. Это не проект с открытым исходным кодом, и я не ожидаю, что будут "плагины". Смысл в том, чтобы упростить основной код приложения и избавить от необходимости изменять его каждый раз, когда добавляется новый командный модуль.

456
задан Jonathan Rolfsen 13 August 2019 в 11:57
поделиться

4 ответа

С Python, более старым, чем 2.7/3.1, это в значительной степени, как Вы делаете это.

Для более новых версий, см. importlib.import_module для Python 2 и и Python 3 .

, который можно использовать exec, если Вы хотите также.

Или использование __import__ можно импортировать список модулей путем выполнения этого:

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

Разорванный прямо от Погружение В Python .

278
ответ дан Bhargav Rao 13 August 2019 в 11:57
поделиться
  • 1
    @Anshuman I' m не уверенный, если я понял Ваш вопрос. Если Вы хотите попросить, чтобы пользователю для выбора почтовой программы действительно понравилось, объяснен в этом сообщении: stackoverflow.com/questions/2077008/… – Derzu 3 September 2012 в 15:01

Можно использовать exec :

exec "import myapp.commands.%s" % command
10
ответ дан Greg Hewgill 13 August 2019 в 11:57
поделиться

Используйте модуль импорта , или более прямое __import__() функция.

19
ответ дан gimel 13 August 2019 в 11:57
поделиться
  • 1
    Имейте перечитанный из ответа. Неважно, если windowFullscreen имеет значение true, ложь или isn' t подарок, Ваше Действие все еще будет полным экраном. – Graeme 8 October 2012 в 08:27

Примечание: импорт удерживается от использования начиная с Python 3.4 в пользу importlib

, Как упомянуто импорт модуль предоставляет Вам загружающий функции:

imp.load_source(name, path)
imp.load_compiled(name, path)

я использовал их прежде для выполнения чего-то подобного.

В моем случае я определил определенный класс с определенными методами, которые требовались. Как только я загрузил модуль, который я проверю, был ли класс в модуле, и затем создайте экземпляр того класса, чего-то вроде этого:

import imp
import os

def load_from_file(filepath):
    class_inst = None
    expected_class = 'MyClass'

    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    if file_ext.lower() == '.py':
        py_mod = imp.load_source(mod_name, filepath)

    elif file_ext.lower() == '.pyc':
        py_mod = imp.load_compiled(mod_name, filepath)

    if hasattr(py_mod, expected_class):
        class_inst = getattr(py_mod, expected_class)()

    return class_inst
128
ответ дан Brian Burns 13 August 2019 в 11:57
поделиться
  • 1
    да.. мне установили FB. Я в состоянии совместно использовать любой URL к FB, но не простой текст совместного использования... может u помогать.. – Sudipta Som 28 November 2012 в 08:56
Другие вопросы по тегам:

Похожие вопросы: