207

Python クラスの文字列が与えられた場合、たとえばmy_package.my_module.MyClass、それをロードする最善の方法は何ですか?

言い換えればClass.forName()、Java で同等のもの、Python で機能するものを探しています。Google App Engine で動作する必要があります。

これは、クラスの FQN を文字列として受け取り、クラスへの参照を返す関数であることが望ましいです。

my_class = load_class('my_package.my_module.MyClass')
my_instance = my_class()
4

11 に答える 11

168

独自のロールを作成したくない場合は、pydocまさにこれを行うモジュールで利用可能な関数があります。

from pydoc import locate
my_class = locate('my_package.my_module.MyClass')

ここにリストされている他のアプローチに対するこのアプローチの利点は、モジュール内の直接のオブジェクトだけでなく、指定されたドット パスで任意のlocatepython オブジェクトを見つけることです。例えば。my_package.my_module.MyClass.attr

彼らのレシピが何であるかに興味があるなら、ここに機能があります:

def locate(path, forceload=0):
    """Locate an object by name or dotted path, importing as necessary."""
    parts = [part for part in split(path, '.') if part]
    module, n = None, 0
    while n < len(parts):
        nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
        if nextmodule: module, n = nextmodule, n + 1
        else: break
    if module:
        object = module
    else:
        object = __builtin__
    for part in parts[n:]:
        try:
            object = getattr(object, part)
        except AttributeError:
            return None
    return object

機能に依存しpydoc.safeimportます。そのためのドキュメントは次のとおりです。

"""Import a module; handle errors; return None if the module isn't found.

If the module *is* found but an exception occurs, it's wrapped in an
ErrorDuringImport exception and reraised.  Unlike __import__, if a
package path is specified, the module at the end of the path is returned,
not the package at the beginning.  If the optional 'forceload' argument
is 1, we reload the module from disk (unless it's a dynamic extension)."""
于 2014-07-17T23:52:06.197 に答える
154
import importlib

module = importlib.import_module('my_package.my_module')
my_class = getattr(module, 'MyClass')
my_instance = my_class()
于 2013-10-07T14:55:19.610 に答える
35

Django を使用している場合は、これを使用できます。はい、OPがdjangoを要求しなかったことは承知していますが、Djangoの解決策を探してこの質問に出くわし、見つけられなかったので、それを探す次の少年/ギャルのためにここに置きました。

# It's available for v1.7+
# https://github.com/django/django/blob/stable/1.7.x/django/utils/module_loading.py
from django.utils.module_loading import import_string

Klass = import_string('path.to.module.Klass')
func = import_string('path.to.module.func')
var = import_string('path.to.module.var')

.、like re、またはargparseuseを持たないものをインポートする場合は、次のことに注意してください。

re = __import__('re')

の公式ドキュメントはこちらですimport_string

于 2019-04-09T18:49:57.827 に答える
29
def import_class(cl):
    d = cl.rfind(".")
    classname = cl[d+1:len(cl)]
    m = __import__(cl[0:d], globals(), locals(), [classname])
    return getattr(m, classname)
于 2011-11-24T09:49:03.757 に答える