Pregunta

Para propósitos de registro Quiero recuperar el nombre de clase completo de un objeto de Python. (Con completo me refiero al nombre de la clase que incluye el paquete y el nombre del módulo.)

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

¿Fue útil?

Solución

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 Bar define como

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

la salida es

$ ./prog.py
foo.Bar

Otros consejos

Las respuestas proporcionadas no se ocupan de clases anidadas. Aunque no está disponible hasta Python 3.3 ( PEP 3155 ), que realmente desea utilizar __qualname__ de la clase. Finalmente (3.4? PEP 395 ), __qualname__ también existirá para los módulos para hacer frente a los casos en que se cambia el nombre del módulo (es decir, cuando se cambia a __main__).

Considere el uso del módulo inspect que tiene funciones como getmodule que podría ser lo que buscas:

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

Esto es una basada en la excelente respuesta de Greg Bacon, pero con un par de comprobaciones adicionales:

__module__ puede None (de acuerdo con los documentos), y también para un tipo como str se puede __builtin__ (que puede que no desee que aparece en los registros o lo que sea). Los siguientes controles para ambos esas 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 comprobar si hay __builtin__. Lo anterior simplemente se basa en el hecho de que str siempre está disponible, y su módulo es siempre __builtin__)

__module__ haría el truco.

Probar:

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

Este sitio sugiere que __package__ podría funcionar para Python 3.0; Sin embargo, los ejemplos dados no trabajarán bajo mi consola Python 2.5.2.

Este es un truco, pero estoy apoyando 2,6 y sólo necesita algo simple:

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

'logging.handlers.MemoryHandler'

Algunas personas (por ejemplo, https://stackoverflow.com/a/16763814/5766934 ) argumentando que es mejor __qualname__ que __name__. Aquí es 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>

Para python3.7 que utilizo:

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

Cómo:

package.subpackage.ClassName

Dado que el interés de este tema es conseguir nombres completos, aquí es una trampa que se produce cuando se utilizan las importaciones en relación con el módulo principal existente en el mismo paquete. Por ejemplo, con la configuración del módulo a continuación:

$ 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á la salida que muestra el resultado de la importación de un mismo módulo de forma 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 las importaciones de barras de zumbido utilizando una ruta relativa, bar Baz.__module__ ve simplemente como "Baz", pero en la segunda importación que utiliza el nombre completo, la barra ve lo mismo que "foo.baz".

Si está persistiendo los nombres totalmente calificados en alguna parte, es mejor evitar las importaciones en relación a esas clases.

Ninguna de las respuestas aquí trabajado para mí. En mi caso, yo estaba usando Python 2.7 y sabía que sólo estaría trabajando con clases object newstyle.

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top