Как импортировать модуль по названию? - PullRequest
440 голосов
/ 19 ноября 2008

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

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

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

Ответы [ 12 ]

0 голосов
/ 19 сентября 2017

У меня работал следующий кусок:

>>>import imp; 
>>>fp, pathname, description = imp.find_module("/home/test_module"); 
>>>test_module = imp.load_module("test_module", fp, pathname, description);
>>>print test_module.print_hello();

если вы хотите импортировать в shell-скрипт:

python -c '<above entire code in one line>'
0 голосов
/ 20 августа 2010

У меня сработало следующее:

import sys, glob
sys.path.append('/home/marc/python/importtest/modus')
fl = glob.glob('modus/*.py')
modulist = []
adapters=[]
for i in range(len(fl)):
    fl[i] = fl[i].split('/')[1]
    fl[i] = fl[i][0:(len(fl[i])-3)]
    modulist.append(getattr(__import__(fl[i]),fl[i]))
    adapters.append(modulist[i]())

Загружает модули из папки 'modus'. Модули имеют один класс с тем же именем, что и имя модуля. Например. файл modus / modu1.py содержит:

class modu1():
    def __init__(self):
        self.x=1
        print self.x

Результатом является список динамически загружаемых классов «адаптеров».

...