파이썬에서 객체의 정규화 된 클래스 이름을 얻습니다.


136

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

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

답변:


147

다음 프로그램으로

#! /usr/bin/env python

import foo

def fullname(o):
  # o.__module__ + "." + o.__class__.__qualname__ is an example in
  # this context of H.L. Mencken's "neat, plausible, and wrong."
  # Python makes no guarantees as to whether the __module__ special
  # attribute is defined, so we take a more circumspect approach.
  # Alas, the module name is explicitly excluded from __qualname__
  # in Python 3.

  module = o.__class__.__module__
  if module is None or module == str.__class__.__module__:
    return o.__class__.__name__  # Avoid reporting __builtin__
  else:
    return module + '.' + o.__class__.__name__

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

Bar정의

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

출력은

$ ./prog.py
foo.Bar

2
이것은 바가 정의 된 위치가 아니라 바가 정의 된 모듈을 반환하는 것으로 보입니다. 로깅의 목적이 어떤 종류의 객체인지 정확히 아는 것이 도움이되지 않는 것 같습니다.
Mark E. Haase

인가 o.__class__.__module__에서 이제까지 다른 o.__module__?
larsks


1
저는 ".".join([o.__module__, o.__name__])Python3을 강력히 추천 합니다
Piotr Pęczek

때때로 작동하지 않습니다 :AttributeError: 'AttributeError' object has no attribute '__module__'
Hendy Irawan

38

제공된 답변은 중첩 클래스를 처리하지 않습니다. Python 3.3 ( PEP 3155 ) 까지는 사용할 수 없지만 실제로 __qualname__클래스 를 사용하고 싶습니다 . 결국 (3.4? PEP 395 ) __qualname__는 모듈의 이름이 변경되는 경우 (즉, 이름이으로 변경되는 경우)를 처리하기 위해 모듈에도 존재합니다 __main__.


3
당신이 사용하는 경우 github.com/wbolster/qualname을 당신은 얻을 수 qualname의 이전 버전에 해당합니다.
wouter bolsterlee

3
Type.__module__ + '.' + Type.__qualname__.
Kentzo

4
Python 3.6에서는 클래스 이름 만 제공됩니다. 모듈은 포함되어 있지 않습니다.
jpmc26

2
@ jpmc26 파이썬 3.7에서는 __qualname__여전히 클래스 이름으로 만 해석됩니다.
zepp.lee

22

찾고있는 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'>

7
inspect.getmodule()정규화 된 클래스 이름이 아닌 모듈 객체를 반환 합니다. 실제로이 inspect모듈은 실제로이 문제를 해결하는 기능을 제공하지 않습니다. 이 답변은 답변이 아닙니다. </facepalm>
세실 카레

19

다음은 Greg Bacon의 훌륭한 답변을 기반으로하지만 몇 가지 추가 검사가 있습니다.

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


1
Greg Bacon의 답변에있는 코드는 Greg가 무의미한 else 문과 일부 코드 주석을 추가 한 것 외에는이 코드의 코드와 동일합니다. MB는 진정한 영웅입니다.
MarredCheese


9

__module__ 트릭을 할 것입니다.

시험:

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

이 사이트__package__Python 3.0에서 작동 할 수 있다고 제안합니다 . 그러나 주어진 예제는 Python 2.5.2 콘솔에서 작동하지 않습니다.


6
그 트릭을 수행합니다, 감사합니다! 정규화 된 이름으로 사용합니다 "%s.%s" % (x.__class__.__module__, x.__class__.__name__)
Hanno S.

7

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

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

'logging.handlers.MemoryHandler'

1
이것은에 따라 __repr__()확인 된 클래스의 구현 ( __str__()오버라이드 (override)되지 않는). 대부분의 경우 쓸모가 없습니다.
z33k

7

어떤 사람들은 (예 : 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

buildins에서도 올바르게 작동합니다.

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

2

이 주제의 관심은 완전한 이름을 얻는 것이므로, 동일한 패키지에 존재하는 기본 모듈과 함께 상대 가져 오기를 사용할 때 발생하는 함정이 있습니다. 예를 들어, 아래 모듈 설정으로 :

$ 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이 상대 경로를 사용하여 bar를 가져 오는 경우 bar는 Baz.__module__"baz"로 표시되지만 전체 이름을 사용하는 두 번째 가져 오기에서는 bar가 "foo.baz"와 동일합니다.

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


0

여기에 대한 답변 중 어느 것도 나를 위해 일하지 않았습니다. 필자의 경우 Python 2.7을 사용하고 있었고 새 스타일 object클래스 로만 작업한다는 것을 알고있었습니다 .

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.