it-swarm.com.de

Importieren Sie eine Methode dynamisch aus einer Zeichenfolge in eine Datei

Ich habe eine Zeichenfolge, sagen Sie: abc.def.ghi.jkl.myfile.mymethod. Wie importiere ich dynamisch mymethod?

So habe ich es gemacht:

def get_method_from_file(full_path):
    if len(full_path) == 1:
        return map(__import__,[full_path[0]])[0]
    return getattr(get_method_from_file(full_path[:-1]),full_path[-1])


if __name__=='__main__':
    print get_method_from_file('abc.def.ghi.jkl.myfile.mymethod'.split('.'))

Ich frage mich, ob der Import einzelner Module überhaupt erforderlich ist.

Edit: Ich verwende Python Version 2.6.5.

56
Lakshman Prasad

Ab Python 2.7 können Sie die Funktion importlib.import_module () verwenden. Sie können ein Modul importieren und mit folgendem Code auf ein darin definiertes Objekt zugreifen:

from importlib import import_module

p, m = name.rsplit('.', 1)

mod = import_module(p)
met = getattr(mod, m)

met()
78
frm

Sie müssen die einzelnen Module nicht importieren. Es reicht aus, das Modul, aus dem Sie einen Namen importieren möchten, zu importieren und das Argument fromlist anzugeben:

def import_from(module, name):
    module = __import__(module, fromlist=[name])
    return getattr(module, name)

Rufen Sie für Ihr Beispiel abc.def.ghi.jkl.myfile.mymethod diese Funktion als auf

import_from("abc.def.ghi.jkl.myfile", "mymethod")

(Beachten Sie, dass Funktionen auf Modulebene in Python als Funktionen bezeichnet werden, nicht als Methoden.)

Für eine solche einfache Aufgabe bietet die Verwendung des Moduls importlib keinen Vorteil.

25
Sven Marnach

Für Python <2.7 kann die eingebaute Methode _ IMPORT_ verwendet werden:

__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])

Für Python> = 2.7 oder 3.1 wurde die praktische Methode importlib.import_module hinzugefügt. Importiere dein Modul einfach so:

importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')

Update: Aktualisierte Version gemäß Kommentaren (Ich muss zugeben, dass ich die zu importierende Zeichenfolge bis zum Ende nicht gelesen habe. Ich habe die Tatsache übersehen, dass eine Methode eines Moduls importiert werden sollte und kein Modul selbst ):

Python <2,7:

mymethod = getattr(__import__("abc.def.ghi.jkl.myfile", fromlist=["mymethod"]))

Python> = 2,7:

mymethod = getattr(importlib.import_module("abc.def.ghi.jkl.myfile"), "mymethod")
18
gecco

Es ist nicht klar, was Sie mit Ihrem lokalen Namespace tun möchten. Ich nehme an, Sie möchten nur my_method als lokale, output = my_method() eingeben? 

# This is equivalent to "from a.b.myfile import my_method"
the_module = importlib.import_module("a.b.myfile")
same_module = __import__("a.b.myfile")
# import_module() and __input__() only return modules
my_method = getattr(the_module, "my_method")

# or, more concisely,
my_method = getattr(__import__("a.b.myfile"), "my_method")
output = my_method()

Während Sie nur my_method zum lokalen Namespace hinzufügen, laden Sie die Modulkette. Sie können Änderungen anzeigen, indem Sie die Schlüssel von sys.modules vor und nach dem Import ansehen. Ich hoffe, das ist klarer und genauer als Ihre anderen Antworten.

Der Vollständigkeit halber fügen Sie die gesamte Kette hinzu.

# This is equivalent to "import a.b.myfile"
a = __import__("a.b.myfile")
also_a = importlib.import_module("a.b.myfile")
output = a.b.myfile.my_method()

# This is equivalent to "from a.b import myfile"
myfile = __import__("a.b.myfile", fromlist="a.b")
also_myfile = importlib.import_module("a.b.myfile", "a.b")
output = myfile.my_method()

Wenn Sie __import__() verwenden und Ihren Suchpfad nach dem Programmstart geändert haben, müssen Sie möglicherweise __import__(normal args, globals=globals(), locals=locals()) verwenden. Das Warum ist eine komplexe Diskussion.

5
Charles Merriam
from importlib import import_module


name = "file.py".strip('.py')
# if Path like : "path/python/file.py" 
# use name.replaces("/",".")

imp = import_module(name)

# get Class From File.py
model = getattr(imp, "naemClassImportFromFile")

NClass = model() # Class From file 
2
Alaa Akiel

Wie ich dazu neige (wie auch einige andere Bibliotheken, z. B. Pylonen und Einfügen, wenn mir das Gedächtnis gut tut), ist die Trennung des Modulnamens vom Funktions-/Attributnamen, indem ein ':' zwischen ihnen verwendet wird . Siehe folgendes Beispiel:

'abc.def.ghi.jkl.myfile:mymethod'

Dies macht die Funktion import_from(path) etwas einfacher zu bedienen.

def import_from(path):
    """
    Import an attribute, function or class from a module.
    :attr path: A path descriptor in the form of 'pkg.module.submodule:attribute'
    :type path: str
    """
    path_parts = path.split(':')
    if len(path_parts) < 2:
        raise ImportError("path must be in the form of pkg.module.submodule:attribute")
    module = __import__(path_parts[0], fromlist=path_parts[1])
    return getattr(module, path_parts[1])


if __name__=='__main__':
    func = import_from('a.b.c.d.myfile:mymethod')
    func()
0
Kris Hardy

Diese Website hat eine schöne Lösung: load_class . Ich benutze es so:

foo = load_class(package.subpackage.FooClass)()
type(foo) # returns FooClass

Wie gewünscht, hier der Code aus dem Weblink:

import importlib

def load_class(full_class_string):
    """
    dynamically load a class from a string
    """

    class_data = full_class_string.split(".")
    module_path = ".".join(class_data[:-1])
    class_str = class_data[-1]

    module = importlib.import_module(module_path)
    # Finally, we retrieve the Class
    return getattr(module, class_str)
0
kingaj

Wie wäre es damit :

def import_module(name):

    mod = __import__(name)
    for s in name.split('.')[1:]:
        mod = getattr(mod, s)
    return mod
0
Aymen Alsaadi