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


84

私は文字列を持っています、例えば: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を使用しています。

回答:


111

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

2
Pythonのドキュメントを注目に値するが使用することをお勧めimportlib.import_module()オーバー__import__()docs.python.org/2/library/functions.html#__import__を- 2.7以降のために。
ボルツマン

4
import_module + rsplit = 1つの真の方法。
セシルカレー

32

個々のモジュールをインポートする必要はありません。名前をインポートするモジュールをインポートし、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モジュールを使用する利点はありません。


import_from()は私を正しい方向に向けました。myClass = getattr(__import__("module.to.import", fromlist=["myClassName"]), "myClassName")。助けてくれてありがとう!
fydo 2014年

1
この__import__アプローチは機能します。しかし、実行してみてくださいhelp(__import__)。「この関数はPythonインタープリターによる使用を目的としており、一般的な使用を目的としていないためimportlib.import_module()、プログラムでモジュールをインポートするために使用することをお勧めします。」
twasbrillig 2015

5
@twasbrillig:この質問に答えたとき、Python2.5と2.6はまだ広く使用されていました。今日では、importlib代わりに使用するのが確かに最善です。
Sven Marnach 2015

1
かっこいい、ありがとう。これを反映するように回答を更新することをお勧めします。
twasbrillig 2015

26

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

6
これらのソリューションのどちらも最初のパラメータがなければならないので、動作しませんモジュール名の両方に__import__()importlib.import_module()
Kris Hardy

1
importlib.import_module( 'abc.def.ghi.jkl.myfile.mymethod')は、メソッドの「修飾」名ではなく、「絶対または相対用語でインポートするモジュール」を指定する必要があるため、機能しません。
frm 2012年

インポートする最初のパラメーターは文字列ではなくモジュールである必要があるため、これは明らかに機能しません。
ラクシュマンプラサド2012年

11

ローカル名前空間に対して何をしようとしているのかは不明です。私はあなたがちょうど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())。なぜ複雑な議論なのか。


あなたの最初の例the_modulesame_module間違っていると異なる結果を生成します。反対票。
sleepycal 2014

7
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, "classNameImportFromFile")

NClass = model() # Class From file 

2
答えてくれてありがとう、ただ一つの小さな問題:.strip()あなたが言った場合には正しく振る舞わないと思います。具体的には、ファイルが「py」で始まる場合、それらの文字も削除されます。たとえば、"pyfile.py".strip(".py")"file"生成"pyfile"します。この場合は、を生成することが望ましいです。name.replace(".py","")ただし、問題なく動作します。
jxmorris 1220年

1

このウェブサイトには素晴らしい解決策があります: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)

与えられたリンクからの要約/コードを含めてください。リンク切れが発生しやすいため、リンクのみの回答は適切ではありません。
さらに別のユーザー

0

使用しますimportlib(2.7以降のみ)。


1
2.6.5を使用しています。私はfrom __future__何かをすることができますか?
ラクシュマンプラサド2012年

5
いいえ、__future__言語機能用であり、新しいstdlibモジュール用ではありません。
ThiefMaster 2012年

1
__import__上記の例のようにbuit-inを使用します。2.5に戻り、キーワードなしでそれ以前に機能します。
チャールズメリアム2013年

0

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

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

1
なぜanybdoyはこれを行う必要がありますか?これには、呼び出し元がモジュール名と属性名をコロンで結合する必要があり、関数はコロンで再度分割する必要があります。そもそも2つのパラメータを単純に使用してみませんか?
Sven Marnach 2012年

1
多くの場合、これが発生する状況は、構成ファイル(.yaml、.iniなど)を使用してフレームワークからアプリケーションにコールバックをワイヤリングする場合です。次に、構成ファイル内の単一の文字列を使用して、フレームワークが呼び出す関数などを指定できます。
クリスハーディ

そうですね、これを構成ファイルの構文として選択することをお勧めします。しかし、これはOPの質問とどのように関連していますか?(これを構成ファイルの構文として選択した場合でも、ランダムなAPI関数ではなく、構成ファイルパーサーで解析することをお
勧めし

-1

これはどう :

def import_module(name):

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

魔法の方法を使用することはお勧めしません。代わりにimportlibを使用してください。
dephinera

なぜそれが落胆しているのか詳しく説明できますか?@dephinera
AymenAlsaadi20年

マジックメソッドは、コードによって明示的にではなく、インタプリタによって呼び出されることを目的としているためです。それらを明示的に呼び出すことにより、それらの署名が決して変更されないことを信頼しますが、将来の言語バージョンで変更される可能性があります。
dephinera
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.