імпортний модуль зі змінної рядка


183

Я працюю над документацією (персональною) для вкладеної бібліотеки matplotlib (MPL), яка відрізняється від наданої MPL пакетами зацікавлених пакетів підмодулів. Я пишу сценарій Python, який, сподіваюся, автоматизує генерацію документів з майбутніх версій MPL.
Я вибрав зацікавлені підмодулі / пакети і хочу перерахувати їх основні класи, з яких буду генерувати список та обробляти йогоpydoc

Проблема полягає в тому, що я не можу знайти спосіб доручити Python завантажувати підмодуль з рядка. Ось приклад того, що я спробував:

import matplotlib.text as text
x = dir(text)

.

i = __import__('matplotlib.text')
y = dir(i)

.

j = __import__('matplotlib')
z = dir(j)

Ось три порівняння вищезазначених списків через pprint:

введіть тут опис зображення

Я не розумію, що завантажено в yоб'єкт - це база matplotlibплюс щось інше, але в ньому відсутня інформація, яку я хотів, і це основні класи з matplotlib.textпакета. Це верхня частина синього кольору на екрані ( xсписок)

Будь ласка, не пропонуйте Сфінкса як іншого підходу.


Чи можете ви пояснити, для чого вам потрібно скористатися, __import__(str)а не стандартним importдержавом?
thesamet

Це тому, що я обробляю списки, які елементи є підмодулями MPL та отримую їхні шляхи методів
theta

9
@thesamet - c'mon - є нескінченні ідеї, де ви б хотіли цю функціональність. Коли у вас є текстова конфігурація бібліотек, ви можете завантажувати їх за назвою, що не буде працювати з importоператором. Ось один приклад використання: djangosnippets.org/snippets/3048
Tomasz

Відповіді:


279

__import__Функція може бути трохи важко зрозуміти.

Якщо ти змінишся

i = __import__('matplotlib.text')

до

i = __import__('matplotlib.text', fromlist=[''])

потім iбуде посилатися на matplotlib.text.

У Python 2.7 та Python 3.1 або новіших версіях ви можете використовувати importlib:

import importlib

i = importlib.import_module("matplotlib.text")

Деякі примітки

  • Якщо ви намагаєтесь імпортувати щось із підпапки, наприклад ./feature/email.py, код буде мати такий виглядimportlib.import_module("feature.email")

  • Ви нічого не можете імпортувати, якщо __init__.pyу папці з файлом, який ви намагаєтеся імпортувати, немає


3
importlibмає бути доступним на pypi для <python2.7
Джеффрі Хосе

50
Для всіх, хто приїжджає сюди з Google. Слід зазначити, що якщо ви намагаєтесь імпортувати щось із підпапки (наприклад, ./feature/email.py), код буде мати виглядimportlib.import_module("feature.email")
Seanny123

11
Нарешті, також пам’ятайте, що ви нічого не можете імпортувати, якщо __init__.pyу папці з файлом, який ви намагаєтеся імпортувати, немає.
Seanny123

3
@mzjn Це для import moduleNameрядка moduleName. Як щодо from moduleName import *?
Нам Г ВУ

2
Щойно знайшов відповідь на моє запитання тут на випадок, якщо комусь
Nam G VU

68

importlib.import_moduleце те, що ви шукаєте. Він повертає імпортований модуль. (Доступно лише для Python> = 2.7 або 3.x):

import importlib

mymodule = importlib.import_module('matplotlib.text')

Після цього ви можете отримати доступ до будь-якого модуля як mymodule.myclassтощо.


Альтернативою є imp.load_source(..)використання impмодуля, як запропоновано у цій відповіді stackoverflow.com/questions/67631/…
Євгеній Сергєєв,

5
@gecco Це для import moduleNameрядка moduleName. Як щодо from moduleName import *?
Нам Г ВУ

6

витратив деякий час на імпорт модулів зі списку, і це нитка, яка перенесла мене більшу частину шляху - але я не зрозумів використання ___import____ -

тож ось як імпортувати модуль із рядка та отримувати таку ж поведінку, що й просто імпортувати. І спробуйте / крім випадку помилки теж. :)

  pipmodules = ['pycurl', 'ansible', 'bad_module_no_beer']
  for module in pipmodules:
      try:
          # because we want to import using a variable, do it this way
          module_obj = __import__(module)
          # create a global object containging our module
          globals()[module] = module_obj
      except ImportError:
          sys.stderr.write("ERROR: missing python module: " + module + "\n")
          sys.exit(1)

і так, для python 2.7> у вас є інші варіанти - але для 2.6 <це працює.


1

Я розробив ці 3 корисні функції:

def loadModule(moduleName):
    module = None
    try:
        import sys
        del sys.modules[moduleName]
    except BaseException as err:
        pass
    try:
        import importlib
        module = importlib.import_module(moduleName)
    except BaseException as err:
        serr = str(err)
        print("Error to load the module '" + moduleName + "': " + serr)
    return module

def reloadModule(moduleName):
    module = loadModule(moduleName)
    moduleName, modulePath = str(module).replace("' from '", "||").replace("<module '", '').replace("'>", '').split("||")
    if (modulePath.endswith(".pyc")):
        import os
        os.remove(modulePath)
        module = loadModule(moduleName)
    return module

def getInstance(moduleName, param1, param2, param3):
    module = reloadModule(moduleName)
    instance = eval("module." + moduleName + "(param1, param2, param3)")
    return instance

І кожного разу, коли я хочу перезавантажити новий екземпляр, я просто повинен викликати getInstance () так:

myInstance = getInstance("MyModule", myParam1, myParam2, myParam3)

Нарешті, я можу зателефонувати всім функціям нового екземпляра:

myInstance.aFunction()

Єдина специфіка тут - налаштувати список парам (param1, param2, param3) вашого примірника.


1

Крім використання importlibодного, можна також використовувати execметод імпорту модуля зі змінної рядка.

Тут я показую приклад імпорту combinationsметоду з itertoolsпакета за допомогою execметоду:

MODULES = [
    ['itertools','combinations'],
]

for ITEM in MODULES:
    import_str = "from {0} import {1}".format(ITEM[0],', '.join(str(i) for i in ITEM[1:]))
    exec(import_str)

ar = list(combinations([1, 2, 3, 4], 2))
for elements in ar:
    print(elements)

Вихід:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.