[python] 문자열을 파이썬 클래스 객체로 변환 하시겠습니까?

파이썬 함수에 대한 사용자 입력으로 문자열이 주어지면 현재 정의 된 네임 스페이스에 해당 이름의 클래스가있는 경우 클래스 객체를 가져 오려고합니다. 본질적으로 이러한 종류의 결과를 생성하는 함수에 대한 구현을 원합니다.

class Foo:
    pass

str_to_class("Foo")
==> <class __main__.Foo at 0x69ba0>

이것이 가능합니까?



답변

경고 : eval()임의의 파이썬 코드를 실행하는 데 사용할 수 있습니다. 신뢰할 수없는 문자열과 함께 사용 해서는 안됩니다eval() . ( 신뢰할 수없는 문자열에 대한 Python eval ()의 보안? )

가장 간단한 것 같습니다.

>>> class Foo(object):
...     pass
...
>>> eval("Foo")
<class '__main__.Foo'>


답변

이것은 작동 할 수 있습니다 :

import sys

def str_to_class(classname):
    return getattr(sys.modules[__name__], classname)


답변

당신은 다음과 같은 것을 할 수 있습니다 :

globals()[class_name]


답변

Baz모듈에 있는 클래스 가 필요합니다 foo.bar. Python 2.7에서는을 사용하려고 importlib.import_module()합니다. Python 3으로 쉽게 전환 할 수 있습니다.

import importlib

def class_for_name(module_name, class_name):
    # load the module, will raise ImportError if module cannot be loaded
    m = importlib.import_module(module_name)
    # get the class, will raise AttributeError if class cannot be found
    c = getattr(m, class_name)
    return c

파이썬 <2.7에서 :

def class_for_name(module_name, class_name):
    # load the module, will raise ImportError if module cannot be loaded
    m = __import__(module_name, globals(), locals(), class_name)
    # get the class, will raise AttributeError if class cannot be found
    c = getattr(m, class_name)
    return c

사용하다:

loaded_class = class_for_name('foo.bar', 'Baz')


답변

import sys
import types

def str_to_class(field):
    try:
        identifier = getattr(sys.modules[__name__], field)
    except AttributeError:
        raise NameError("%s doesn't exist." % field)
    if isinstance(identifier, (types.ClassType, types.TypeType)):
        return identifier
    raise TypeError("%s is not a class." % field)

이것은 구식과 신식 수업을 정확하게 처리합니다.


답변

django가 이것을 처리하는 방법을 보았습니다.

django.utils.module_loading이 가지고 있습니다

def import_string(dotted_path):
    """
    Import a dotted module path and return the attribute/class designated by the
    last name in the path. Raise ImportError if the import failed.
    """
    try:
        module_path, class_name = dotted_path.rsplit('.', 1)
    except ValueError:
        msg = "%s doesn't look like a module path" % dotted_path
        six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])

    module = import_module(module_path)

    try:
        return getattr(module, class_name)
    except AttributeError:
        msg = 'Module "%s" does not define a "%s" attribute/class' % (
            module_path, class_name)
        six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])

당신은 그것을 사용할 수 있습니다 import_string("module_path.to.all.the.way.to.your_class")


답변

예, 당신은 이것을 할 수 있습니다. 클래스가 전역 네임 스페이스에 있다고 가정하면 다음과 같이됩니다.

import types

class Foo:
    pass

def str_to_class(s):
    if s in globals() and isinstance(globals()[s], types.ClassType):
            return globals()[s]
    return None

str_to_class('Foo')

==> <class __main__.Foo at 0x340808cc>