programing

Python에서 개체의 정규화된 클래스 이름 가져오기

elecom 2023. 6. 7. 22:10
반응형

Python에서 개체의 정규화된 클래스 이름 가져오기

로깅 목적으로 Python 개체의 정규화된 클래스 이름을 검색하려고 합니다. (완전화된 경우 패키지 및 모듈 이름을 포함하는 클래스 이름을 의미합니다.)

에 대해 알고 있습니다.x.__class__.__name__하지만 패키지와 모듈을 얻을 수 있는 간단한 방법이 있습니까?

다음 프로그램과 함께

#!/usr/bin/env python

import foo

def fullname(o):
    klass = o.__class__
    module = klass.__module__
    if module == 'builtins':
        return klass.__qualname__ # avoid outputs like 'builtins.str'
    return module + '.' + klass.__qualname__

bar = foo.Bar()
print(fullname(bar))

그리고.Bar로 정의된.

class Bar(object):
  def __init__(self, v=42):
    self.val = v

산출물은

$ ./prog.py
foo.Bar

만약 당신이 여전히 파이썬 2에 갇혀 있다면, 당신은 사용해야 할 것입니다.__name__대신에__qualname__중첩 클래스 - 클래스에 대한 정보가 부족합니다.Bar클래스에 내포된Foo로 표시됩니다.Bar대신에Foo.Bar:

def fullname(o):
    klass = o.__class__
    module = klass.__module__
    if module == '__builtin__':
        return klass.__name__ # avoid outputs like '__builtin__.str'
    return module + '.' + klass.__name__

제공된 답변은 중첩된 클래스를 처리하지 않습니다.

Python 3.3(PEP 3155) 이후로는__qualname__대신 학급의__name__그렇지 않으면, 클래스는

class Foo:
    class Bar: # this one
        pass

정당하게 나타날 것입니다.Bar대신에Foo.Bar.

(계속 연결해야 합니다.__module__별도로 -__qualname__모듈 이름을 포함하지 않습니다.)

다음은 그렉 베이컨의 훌륭한 답변을 바탕으로 한 것이지만 몇 가지 추가적인 확인 사항이 있습니다.

__module__수 있습니다.None(문서에 따르면), 그리고 같은 유형에 대해서도.str그럴 수 있다.__builtin__(로그 등에 표시하지 않을 수도 있음).다음은 두 가지 가능성을 모두 확인하는 방법입니다.

def fullname(o):
    module = o.__class__.__module__
    if module is None or module == str.__class__.__module__:
        return o.__class__.__name__
    return module + '.' + o.__class__.__name__

(확인할 수 있는 더 나은 방법이 있을 수 있습니다.__builtin__위의 내용은 str이 항상 사용 가능하고 모듈이 항상 사용 가능하다는 사실에 의존합니다.__builtin__)

python 3.7의 경우 다음을 사용합니다.

".".join([obj.__module__, obj.__name__])

가져오기:

package.subpackage.ClassName

사용을 고려해 보십시오.inspect다음과 같은 기능을 가진 모듈getmodule다음과 같은 것들을 찾고 있습니다.

>>>import inspect
>>>import xml.etree.ElementTree
>>>et = xml.etree.ElementTree.ElementTree()
>>>inspect.getmodule(et)
<module 'xml.etree.ElementTree' from 
        'D:\tools\python2.5.2\lib\xml\etree\ElementTree.pyc'>

일부 사람들(예: https://stackoverflow.com/a/16763814/5766934) )은 다음과 같이 주장합니다.__qualname__보다 낫습니다__name__다음은 차이점을 보여주는 예입니다.

$ cat dummy.py 
class One:
    class Two:
        pass

$ python3.6
>>> import dummy
>>> print(dummy.One)
<class 'dummy.One'>
>>> print(dummy.One.Two)
<class 'dummy.One.Two'>
>>> def full_name_with_name(klass):
...     return f'{klass.__module__}.{klass.__name__}'
>>> def full_name_with_qualname(klass):
...     return f'{klass.__module__}.{klass.__qualname__}'
>>> print(full_name_with_name(dummy.One))  # Correct
dummy.One
>>> print(full_name_with_name(dummy.One.Two))  # Wrong
dummy.Two
>>> print(full_name_with_qualname(dummy.One))  # Correct
dummy.One
>>> print(full_name_with_qualname(dummy.One.Two))  # Correct
dummy.One.Two

기본 제공 기능에 대해서도 올바르게 작동합니다.

>>> print(full_name_with_qualname(print))
builtins.print
>>> import builtins
>>> builtins.print
<built-in function print>

__module__할 수 있을 겁니다

시도:

>>> import re
>>> print re.compile.__module__
re

사이트는 다음을 제안합니다.__package__Python 3.0에서 작동할 수 있습니다. 그러나 여기에 나와 있는 예제는 Python 2.5.2 콘솔에서 작동하지 않습니다.

이것은 해킹이지만 저는 2.6을 지원하며 간단한 것이 필요합니다.

>>> from logging.handlers import MemoryHandler as MH
>>> str(MH).split("'")[1]

'logging.handlers.MemoryHandler'

이 항목에서는 정규화된 이름을 가져오는 데 관심이 있으므로 동일한 패키지에 있는 기본 모듈과 함께 상대 가져오기를 사용할 때 발생하는 함정이 있습니다.예: 아래 모듈 설정:

$ cat /tmp/fqname/foo/__init__.py
$ cat /tmp/fqname/foo/bar.py
from baz import Baz
print Baz.__module__
$ cat /tmp/fqname/foo/baz.py
class Baz: pass
$ cat /tmp/fqname/main.py
import foo.bar
from foo.baz import Baz
print Baz.__module__
$ cat /tmp/fqname/foo/hum.py
import bar
import foo.bar

다음은 동일한 모듈을 다르게 가져온 결과를 보여주는 출력입니다.

$ export PYTHONPATH=/tmp/fqname
$ python /tmp/fqname/main.py
foo.baz
foo.baz
$ python /tmp/fqname/foo/bar.py
baz
$ python /tmp/fqname/foo/hum.py
baz
foo.baz

이 경로를 때 는 hum을 봅니다.Baz.__module__전체 이름을 사용하는 두 번째 가져오기에서는 "foo.baz"와 동일하게 표시됩니다.

전체 이름을 어딘가에 유지하는 경우 해당 클래스에 대한 상대적 가져오기를 피하는 것이 좋습니다.

Bellows는 클래스, 인스턴스, 메서드, 함수, 내장 및 사용자 정의 모두에 대해 테스트된 Greg Bacon의 답변을 개선한 것입니다.

def fullname(o):
    try:
        # if o is a class or function, get module directly
        module = o.__module__
    except AttributeError:
        # then get module from o's class
        module = o.__class__.__module__
    try:
        # if o is a class or function, get name directly
        name = o.__qualname__
    except AttributeError:
        # then get o's class name
        name = o.__class__.__qualname__
    # if o is a method of builtin class, then module will be None
    if module == 'builtins' or module is None:
        return name
    return module + '.' + name

이것은 Greg Bacon과 MB정규 클래스 이름을 사용하기 위해 답변을 수정한 것입니다.질문에 정규화된 클래스 이름이 묻었습니다.Python 3.8로 테스트되었습니다.

def fullname(obj: object) -> str:
    """Return the full name of the given object using its module and qualified class names."""
    # Ref: https://stackoverflow.com/a/66508248/
    module_name, class_name = obj.__class__.__module__, obj.__class__.__qualname__
    if module_name in (None, str.__class__.__module__):
        return class_name
    return module_name + "." + class_name

여기에 있는 어떤 대답도 저에게는 통하지 않았습니다.의 경우, 저는 새로운 의 Python 2.7과만 있었습니다.object 수업. 수업.

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name

내 솔루션은 다음과(와)

def fullname(obj) -> str:
    if type(obj).__qualname__ != "type":
        # obj is instance
        return ".".join(
            [
                obj.__class__.__module__,
                obj.__class__.__qualname__,
            ]
        )
    # obj is not instance
    return ".".join([obj.__module__, obj.__qualname__])
 
 # not instance
 >>> print(fullname(datetime))
 "datetime.datetime"
 # instance
 >>> print(fullname(datetime.now())
 "datetime.datetime"
 # instance
 >>> print(fullname(3))
 "builtins.int"
 

언급URL : https://stackoverflow.com/questions/2020014/get-fully-qualified-class-name-of-an-object-in-python

반응형