web-dev-qa-db-ja.com

文字列からファイルのメソッドを動的にインポートする

文字列があります:abc.def.ghi.jkl.myfile.mymethodmymethodを動的にインポートするにはどうすればよいですか?

ここに私がそれについて行った方法があります:

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('.'))

個々のモジュールをインポートする必要があるのか​​どうか疑問に思っています。

編集:Pythonバージョン2.6.5。

65
Lakshman Prasad

Python 2.7から importlib.import_module() 関数を使用できます。モジュールをインポートし、次のコードでモジュール内で定義されたオブジェクトにアクセスできます。

from importlib import import_module

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

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

met()
91
frm

個々のモジュールをインポートする必要はありません。名前をインポートするモジュールをインポートし、fromlist引数を指定するだけで十分です。

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

たとえば、abc.def.ghi.jkl.myfile.mymethod、この関数を次のように呼び出します

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

(モジュールレベルの関数は、メソッドではなくPythonの関数と呼ばれます。)

このような単純なタスクの場合、importlibモジュールを使用しても利点はありません。

28
Sven Marnach

Python <2.7では組み込みメソッド __ import __ を使用できます:

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

Python> = 2.7または3.1)便利なメソッド importlib.import_module が追加されました。次のようにモジュールをインポートするだけです:

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

更新:コメントに従ってバージョンを更新(最後までインポートする文字列を読んでいなかったことを認めなければなりませんモジュール自体ではなく、モジュールのメソッドをインポートする必要があるという事実を見逃しました)

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")
20
gecco

ローカル名前空間に対して何をしようとしているかは不明です。ローカルとして_my_method_だけが必要で、output = my_method()?と入力すると仮定します。

_# 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()
_

_my_method_をローカル名前空間に追加するだけで、モジュールのチェーンをロードします。インポートの前後に_sys.modules_のキーを見ると、変更を確認できます。これが他の回答よりも明確で正確であることを願っています。

完全を期すために、これがチェーン全体を追加する方法です。

_# 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()
_

そして最後に、__import__()を使用していて、プログラムの開始後に検索パスを変更した場合、__import__(normal args, globals=globals(), locals=locals())を使用する必要があります。その理由は複雑な議論です。

7
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 
4
Alaa Akiel

このWebサイトには、ニースのソリューションがあります: load_class 。私はこれを次のように使用します:

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

要求に応じて、Webリンクからのコードは次のとおりです。

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)
1
kingaj

私がこれに傾向がある方法(および私のメモリが正しく機能する場合、パイロンやペーストなどの他の多くのライブラリ)は、それらの間に「:」を使用してモジュール名を関数/属性名から分離することです。次の例を参照してください。

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

これにより、以下のimport_from(path)関数が少し使いやすくなります。

_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

これはどう :

def import_module(name):

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