文字列があります:abc.def.ghi.jkl.myfile.mymethod
。 mymethod
を動的にインポートするにはどうすればよいですか?
ここに私がそれについて行った方法があります:
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。
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()
個々のモジュールをインポートする必要はありません。名前をインポートするモジュールをインポートし、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
モジュールを使用しても利点はありません。
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")
ローカル名前空間に対して何をしようとしているかは不明です。ローカルとして_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())
を使用する必要があります。その理由は複雑な議論です。
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
この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)
私がこれに傾向がある方法(および私のメモリが正しく機能する場合、パイロンやペーストなどの他の多くのライブラリ)は、それらの間に「:」を使用してモジュール名を関数/属性名から分離することです。次の例を参照してください。
_'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()
_
これはどう :
def import_module(name):
mod = __import__(name)
for s in name.split('.')[1:]:
mod = getattr(mod, s)
return mod