Obtener el nombre de clase completo de un objeto en Python


136

Para fines de registro, quiero recuperar el nombre de clase totalmente calificado de un objeto Python. (Con totalmente calificado me refiero al nombre de la clase, incluido el paquete y el nombre del módulo).

Lo sé x.__class__.__name__, pero ¿hay un método simple para obtener el paquete y el módulo?

Respuestas:


147

Con el siguiente programa

#! /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)

y Bardefinido como

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

la salida es

$ ./prog.py
foo.Bar

2
Esto parece devolver el módulo donde se definió la barra, no donde se definió la barra. Si el propósito del registro es saber exactamente qué tipo de objeto era, entonces esto no parece ayudar.
Mark E. Haase

¿ o.__class__.__module__Alguna vez es diferente de o.__module__?
larsks


1
Recomiendo encarecidamente ".".join([o.__module__, o.__name__])Python3
Piotr Pęczek

A veces no funciona:AttributeError: 'AttributeError' object has no attribute '__module__'
Hendy Irawan

38

Las respuestas proporcionadas no tratan con clases anidadas. Aunque no está disponible hasta Python 3.3 ( PEP 3155 ), realmente desea utilizar __qualname__la clase. Eventualmente (3.4? PEP 395 ), __qualname__también existirá para que los módulos se ocupen de los casos en los que se renombra el módulo (es decir, cuando se renombra __main__).


3
Si usa github.com/wbolster/qualname , puede obtener un equivalente de qualname en versiones anteriores.
wouter bolsterlee

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

44
Con Python 3.6, esto solo me da el nombre de la clase. No incluye el módulo.
jpmc26

2
@ jpmc26 En Python 3.7, __qualname__todavía solo se resuelve con el nombre de la clase
zepp.lee

22

Considere usar el inspectmódulo que tiene funciones como las getmoduleque podrían estar buscando:

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

77
inspect.getmodule()devuelve objetos de módulo : nombres de clase no totalmente calificados. De hecho, el inspectmódulo no proporciona ninguna funcionalidad que realmente aborde esta pregunta. Esta respuesta es una no respuesta. </facepalm>
Cecil Curry

19

Aquí hay uno basado en la excelente respuesta de Greg Bacon, pero con un par de comprobaciones adicionales:

__module__puede ser None(según los documentos), y también para un tipo como strpuede ser __builtin__(que es posible que no desee que aparezca en los registros o lo que sea). Las siguientes comprobaciones para ambas posibilidades:

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__

(Puede haber una mejor manera de verificarlo __builtin__. Lo anterior solo se basa en el hecho de que str siempre está disponible y su módulo siempre está disponible __builtin__)


2
Para salvar a otros el esfuerzo de comparar las dos respuestas: el código en la respuesta de Greg Bacon ahora es idéntico al código en este, aparte de que Greg agregó una declaración inútil y algunos comentarios de código. MB es el verdadero héroe.
MarredCheese

11

Para python3.7 yo uso:

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

Consiguiendo:

package.subpackage.ClassName

tenga en cuenta que objdebe ser una clase en lugar de una instancia de objeto.
Ivan De Paz Centeno

9

__module__ Haría el truco.

Tratar:

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

Este sitio sugiere que __package__podría funcionar para Python 3.0; Sin embargo, los ejemplos dados allí no funcionarán en mi consola Python 2.5.2.


66
Eso funciona, gracias! Para el nombre completo que "%s.%s" % (x.__class__.__module__, x.__class__.__name__)
usaré

7

Este es un truco, pero estoy soportando 2.6 y solo necesito algo simple:

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

'logging.handlers.MemoryHandler'

1
Esto depende de la __repr__()implementación en la clase marcada ( y de __str__()no ser anulada). Inútil en la mayoría de los casos.
z33k

7

Algunas personas (por ejemplo, https://stackoverflow.com/a/16763814/5766934 ) argumentan que __qualname__es mejor que __name__. Aquí hay un ejemplo que muestra la diferencia:

$ 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

Tenga en cuenta que también funciona correctamente para buildins:

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

2

Dado que el interés de este tema es obtener nombres totalmente calificados, aquí hay una trampa que ocurre cuando se usan importaciones relativas junto con el módulo principal existente en el mismo paquete. Por ejemplo, con la siguiente configuración del módulo:

$ 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

Aquí está el resultado que muestra el resultado de importar el mismo módulo de manera diferente:

$ 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

Cuando hum importa la barra usando la ruta relativa, la barra solo ve Baz.__module__"baz", pero en la segunda importación que usa el nombre completo, la barra ve lo mismo que "foo.baz".

Si persiste los nombres completos en alguna parte, es mejor evitar las importaciones relativas para esas clases.


0

Ninguna de las respuestas aquí funcionó para mí. En mi caso, estaba usando Python 2.7 y sabía que solo estaría trabajando con objectclases de estilo nuevo.

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.