Modul aus Stringvariable importieren

181

Ich arbeite an einer (persönlichen) Dokumentation für eine verschachtelte Matplotlib (MPL) -Bibliothek, die sich von der von MPL selbst bereitgestellten durch interessierte Submodul-Pakete unterscheidet. Ich schreibe ein Python-Skript, von dem ich hoffe, dass es die Dokumentgenerierung aus zukünftigen MPL-Versionen automatisiert.
Ich habe interessierte Submodule / Pakete ausgewählt und möchte deren Hauptklassen auflisten, aus denen ich eine Liste erstellen und verarbeiten werdepydoc

Das Problem ist, dass ich keine Möglichkeit finde, Python anzuweisen, das Submodul aus dem String zu laden. Hier ist ein Beispiel für das, was ich versucht habe:

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

.

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

.

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

Und hier ist ein 3-Wege-Vergleich der obigen Listen durch pprint:

Geben Sie hier die Bildbeschreibung ein

Ich verstehe nicht, was in das yObjekt geladen ist - es ist Basis matplotlibplus etwas anderes, aber es fehlen Informationen, die ich wollte, und das sind Hauptklassen aus dem matplotlib.textPaket. Es ist der oberste blau gefärbte Teil auf dem Screenshot ( xListe)

Bitte schlagen Sie Sphinx nicht als anderen Ansatz vor.

Theta
quelle
Können Sie erklären, warum Sie __import__(str)anstelle des Standardstatements verwenden importmüssen?
Thesamet
Das liegt daran, dass ich Listen verarbeiten werde, welche Elemente MPL-Submodule sind, und ihre Methodenpfade abrufen werde
Theta
9
@thesamet - komm schon - es gibt endlose Ideen, wo Sie diese Funktionalität wollen. Wenn Sie eine Textkonfiguration von Bibliotheken haben, können Sie diese nach Namen laden, was mit der importAnweisung nicht ganz funktioniert . Hier ist ein Anwendungsbeispiel: djangosnippets.org/snippets/3048
Tomasz Gandor

Antworten:

278

Die __import__Funktion kann etwas schwer zu verstehen sein.

Wenn Sie sich ändern

i = __import__('matplotlib.text')

zu

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

dann iwird auf verweisen matplotlib.text.

In Python 2.7 und Python 3.1 oder höher können Sie Folgendes verwenden importlib:

import importlib

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

Einige Notizen

  • Wenn Sie versuchen, etwas aus einem Unterordner zu importieren, ./feature/email.pysieht der Code beispielsweise so ausimportlib.import_module("feature.email")

  • Sie können nichts importieren, wenn sich __init__.pyin dem Ordner mit der Datei, die Sie importieren möchten, keine befindet

mzjn
quelle
3
importlibsollte auf pypi für <python2.7
Jeffrey Jose
49
Für alle, die von Google hierher kommen. Es sollte beachtet werden, dass, wenn Sie versuchen, etwas aus einem Unterordner zu importieren (zum Beispiel ./feature/email.py), der Code wie folgt aussiehtimportlib.import_module("feature.email")
Seanny123
11
Denken Sie auch daran, dass Sie nichts importieren können, wenn sich __init__.pyin dem Ordner mit der Datei, die Sie importieren möchten, keine befindet .
Seanny123
3
@mzjn Hier steht import moduleNamemoduleName als Zeichenfolge. Wie wäre es from moduleName import *?
Nam G VU
2
Ich habe gerade eine Antwort auf meine Frage hier gefunden, falls jemand sie benötigt. Stackoverflow.com/a/31306598/248616
Nam G VU
68

importlib.import_moduleist das, wonach Sie suchen. Es gibt das importierte Modul zurück. (Nur für Python> = 2.7 oder 3.x verfügbar):

import importlib

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

Sie können danach auf alles im Modul zugreifen mymodule.myclass, usw.

Gecco
quelle
Eine Alternative ist die imp.load_source(..)Verwendung des impModuls, wie in dieser Antwort vorgeschlagen. Stackoverflow.com/questions/67631/…
Evgeni Sergeev
5
@gecco Hier steht import moduleNamemoduleName als Zeichenfolge. Wie wäre es from moduleName import *?
Nam G VU
6

Ich habe einige Zeit damit verbracht, Module aus einer Liste zu importieren, und dies ist der Thread, der mich den größten Teil des Weges dorthin gebracht hat - aber ich habe die Verwendung von ___import____ nicht verstanden -

Hier erfahren Sie, wie Sie ein Modul aus einer Zeichenfolge importieren und dasselbe Verhalten wie beim Importieren erzielen. Und versuchen Sie / außer dem Fehlerfall auch. :) :)

  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)

und ja, für Python 2.7> haben Sie andere Optionen - aber für 2.6 <funktioniert dies.

daran interessiert
quelle
1

Ich habe diese 3 nützlichen Funktionen entwickelt:

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

Und jedes Mal, wenn ich eine neue Instanz neu laden möchte, muss ich getInstance () wie folgt aufrufen:

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

Endlich kann ich alle Funktionen in der neuen Instanz aufrufen:

myInstance.aFunction()

Die einzige Besonderheit besteht darin, die Parameterliste (param1, param2, param3) Ihrer Instanz anzupassen.

Prossblad
quelle
1

Neben der Verwendung der Methode importlibkann man auch execein Modul aus einer Stringvariablen importieren.

Hier zeige ich ein Beispiel für den Import der combinationsMethode aus einem itertoolsPaket mit der execMethode:

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)

Ausgabe:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
Arsho
quelle