Импортировать файл, используя строку как имя

Возможный дубликат:
Импорт динамического модуля в Python

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

[(folder/filename, bool, bool, int), (folder/filename, bool, bool, int)]

Как вы можете видеть, folder/filename являются одинаковыми (вроде). Имя файла - это имя папки с .py в конце, но при импорте XXX вам не нужно импортировать XXX.py, поэтому я не вижу, чтобы это вызывало проблему.

Проблема, с которой я сталкиваюсь, импортируется с помощью этого метода...

for (testName, auto, hardware, bit) in testList:
    print(testName)
    paths = "\\" + testName
    print paths
    addpath(paths)
    sys.modules[testName] = testName # One of a few options I've seen suggested on the net
    print("Path Added")
    test = testName + ".Helloworld()"
    eval(test)

Итак, для каждого теста у меня есть, напечатайте имя, соберите строку, содержащую путь ("\\testName"), в этом примере напечатайте тестовый путь, затем добавьте путь к списку (sys.path.append(path)), затем распечатать, чтобы подтвердить, что это произошло, а затем собрать строку, которая будет выполняться eval для основного модуля тестов и в конечном итоге оценить его.

Как вы можете видеть, в настоящее время мне нужно иметь список импорта вверху. Я не могу просто импортировать testName (содержимое testName - это имя модуля, который я хочу импортировать), поскольку он попытается найти модуль под названием testName, а не модуль, называемый содержимым testName.

Я видел несколько примеров того, где это было сделано, но не может найти того, что работает в моих обстоятельствах. Если кто-то может буквально бросить кусок кода, который сделает это, было бы замечательно.

Я также просил бы, чтобы я не был висел, ни рисован, ни расквартирован для использования eval, он используется в очень контролируемой среде (список, через который он циклически входит в файл .py, поэтому no "end пользователь" должен возиться с ним).

Ответ 1

Не уверен, правильно ли я все понял, но вы можете импортировать модуль динамически с помощью __import__:

mod = __import__(testName)
mod.HelloWorld()

Изменить: я не знал, что использование __import__ было обескуражено документами python для кода пользователя: Документация __import__ (как отметил Бакуриу)

Это также должно работать и будет считаться лучшим стилем:

import importlib

mod = importlib.import_module(testName)
mod.HelloWorld()

Ответ 2

  • Никогда, никогда, никогда не связывайтесь с sys.modules напрямую, если вы точно не знаете, что делаете.
  • Существует множество способов сделать то, что вы хотите:

Я бы не использовал __import__ напрямую и перешел на importlib.import_module (что также предлагается в конце документации __import__).

Ответ 3

Добавьте путь, по которому модуль находится в sys.path. Импортируйте модуль с помощью функции __import__, которая принимает строчную переменную в качестве имени модуля.

import sys
sys.path.insert(0, mypath)  # mypath = path of module to be imported
imported_module = __import__("string_module_name") # __import__ accepts string 
imported_module.myfunction()   # All symbols in mymodule are now available normally