파이썬 클래스를 동적으로로드하는 방법


167

예를 들어 파이썬 클래스의 문자열이 주어진다면 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()

클래스 참조를 변수에 할당 할 수 있어야합니다.
pjesi

1
이 나타납니다가의 중복이 될 stackoverflow.com/questions/452969/...
cdleary

당신이 옳습니다, 그것을 찾아 주셔서 감사합니다
pjesi

1
파이썬에서 이와 같은 클래스를로드 할 필요가 없었습니다. 모듈이 어디에 있는지 알고 왜 모듈을로드 한 다음 파이썬이 원하는 클래스를 사용하는 것이 훨씬 간단합니다.
Adam Spence

22
이 작업을 수행 할 필요가없는 경우 아직 흥미로운 프로그램을 충분히 작성하지 않았습니다. 계속 연습 해.
John Tyree

답변:


194

파이썬 문서에서 원하는 기능은 다음과 같습니다.

def my_import(name):
    components = name.split('.')
    mod = __import__(components[0])
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

단순 __import__하지 않은 이유는 패키지 문자열의 첫 번째 점을지나 가져온 것을 가져 오는 모듈의 속성이기 때문입니다. 따라서 다음과 같은 것이 작동하지 않습니다.

__import__('foo.bar.baz.qux')

위의 함수를 다음과 같이 호출해야합니다.

my_import('foo.bar.baz.qux')

또는 귀하의 예의 경우 :

klass = my_import('my_package.my_module.my_class')
some_object = klass()

편집 : 나는 이것에 조금 벗어났다. 기본적으로 원하는 것은 다음과 같습니다.

from my_package.my_module import my_class

위의 기능은 비어있는 fromlist 가있는 경우에만 필요합니다 . 따라서 적절한 호출은 다음과 같습니다.

mod = __import__('my_package.my_module', fromlist=['my_class'])
klass = getattr(mod, 'my_class')

my_import ( 'my_package.my_module.my_class')를 시도했지만 모듈이 아닌 클래스이므로 my_class를 찾을 수 없습니다. 나는 my_import 호출 후 클래스를 얻을 gettattr 사용할 수 있습니다 Howver 경우
pjesi

이상하다. 첫 번째 점 이후의 모든 것은 getattr을 사용하여 호출됩니다. 차이가 없어야합니다.
Jason Baker

감사합니다. 이것이 최선의 방법이라고 생각합니다. 이제 문자열 'my_pakcage.my_module.my_class'를 mod_name, klass_name으로 분할하는 가장 좋은 방법 만 필요하지만 알아낼 수있을 것 같습니다 :)
pjesi

2
import 의 python documentation (코드에서)은 importlib를 사용한다고 말합니다. Adam Spence의 답변입니다.
naoko


125

직접 롤링하지 않으려면 pydoc모듈에서 정확히 다음과 같은 기능을 수행 할 수 있습니다 .

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

여기에 나열된 다른 이상이 방법의 장점은이 locate찾을 수 있는 직접 모듈 내에서 제공된 점으로 구분 된 경로에서 파이썬 객체뿐만 아니라 객체를. 예 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)."""

1
나는이 대답을 찬성했다. BTW, 여기에 pydoc을 가져 오는 것이 이상해 보이는 것 같은 safeimport 코드도 있습니다 : github.com/python/cpython/blob/…
brianray

나는이 답변도 찬성했다. 이것은 모든 관련 답변 중 최고입니다.
Sunding Wei

이것은 qualname(모듈 네임 스페이스의 최상위가 아닌 객체) 올바르게 처리 할 수있는 것 같습니다 .
MisterMiyagi

네,하실 수 있습니다locate('my_package.my_module.MyClass.attr.method.etc')
chadrik

109
import importlib

module = importlib.import_module('my_package.my_module')
my_class = getattr(module, 'MyClass')
my_instance = my_class()

9
모듈을 동적으로 가져 오면 모듈을 통해 클래스에 액세스 할 수 있습니다
Adam Spence

더 간결하게 답변을 편집했습니다. 이것이 파이썬에서 클래스를로드하는 가장 좋은 방법입니다.
Adam Spence

BBB- 베니와 스펜스! ;)
dKen

큰! 2.7 이상에서 표준 라이브러리의 일부입니다.
Apteryx

이것은 모듈 / 클래스에 액세스하는 올바른 방법입니다. 워드 프로세서는 여기를 주 : docs.python.org/3/library/importlib.html#importlib.__import__
노엘 에반스

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)

5
이것은 깨끗한 해결책입니다! 당신은 사용을 고려할 수있다 :(modulename, classname) = cl.rsplit('.', 2)
vdboor

그것은 훌륭합니다) 다른 유틸리티와 함께 ​​putils 패키지를 만들었고 클래스를 가져 왔습니다. 원하는 경우 해당 패키지에서 사용할 수 있습니다.
Stan

4
@vdboor rsplit('.', 1)?
Carles Barrobés

글로벌 / 로컬 대신 {}을 (를) 통과했으며 여전히 잘 작동합니다
valtron

17

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

당신이없는 것을 가져 오려면, 명심 .처럼, re또는 argparse사용을 :

re = __import__('re')

5

저는 여기에서 찾을 것을 공유하는 것입니다 __import__importlib이 문제를 해결하기 위해 노력하면서.

Python 3.7.3을 사용하고 있습니다.

I 클래스에 도달 할 때 d모듈 a.b.c,

mod = __import__('a.b.c')

mod변수는 상위 네임 스페이스를 참조하십시오 a.

그래서 클래스에 도착 d, 나는 필요

mod = getattr(mod, 'b') #mod is now module b
mod = getattr(mod, 'c') #mod is now module c
mod = getattr(mod, 'd') #mod is now class d

우리가하려고하면

mod = __import__('a.b.c')
d = getattr(mod, 'd')

우리는 실제로 찾고 있습니다 a.d.

를 사용할 때 importlib라이브러리가 getattr우리를 위해 재귀 를 수행했다고 가정합니다 . 따라서를 사용할 때 importlib.import_module실제로 가장 깊은 모듈에 대한 핸들을 얻습니다.

mod = importlib.import_module('a.b.c') #mod is module c
d = getattr(mod, 'd') #this is a.b.c.d

1

좋아, 그것이 작동하는 방식입니다 (Python 2.7을 사용하고 있습니다).

a = __import__('file_to_import', globals(), locals(), ['*'], -1)
b = a.MyClass()

그런 다음 b는 'MyClass'클래스의 인스턴스입니다.


0

원하는 클래스의 인스턴스가 이미있는 경우 'type'함수를 사용하여 클래스 유형을 추출하고이를 사용하여 새 인스턴스를 구성 할 수 있습니다.

class Something(object):
    def __init__(self, name):
        self.name = name
    def display(self):
        print(self.name)

one = Something("one")
one.display()
cls = type(one)
two = cls("two")
two.display()


-2

Google App Engine에는 webapp2이라는 기능이 import_string있습니다. 자세한 내용은 여기를 참조하십시오 : https://webapp-improved.appspot.com/api/webapp2.html

그래서,

import webapp2
my_class = webapp2.import_string('my_package.my_module.MyClass')

예를 들어 webapp2.Route, 핸들러 또는 문자열을 사용할 수 있는 곳 에서 사용됩니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.