python - barplot - pandas plot
Obtener el nombre de clase totalmente calificado de un objeto en Python (9)
Para fines de registro, quiero recuperar el nombre de clase completamente calificado de un objeto de Python. (Con totalmente calificado me refiero al nombre de la clase, incluido el nombre del paquete y del módulo).
Sé acerca de x.__class__.__name__
, pero ¿hay un método simple para obtener el paquete y el módulo?
Algunas personas (por ejemplo, https://.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>
Aquí hay uno basado en la excelente respuesta de Greg Bacon, pero con un par de controles adicionales:
__module__
puede ser None
(de acuerdo con los documentos), y también para un tipo como str
puede ser __builtin__
(que es posible que no desee que aparezca en los registros o lo que sea). Lo siguiente verifica 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 forma mejor de verificar __builtin__
. Lo anterior simplemente se basa en el hecho de que str está siempre disponible, y su módulo siempre es __builtin__
)
Con el siguiente programa
#! /usr/bin/env python
import foo
def fullname(o):
return o.__module__ + "." + o.__class__.__name__
bar = foo.Bar()
print fullname(bar)
y Bar
definido como
class Bar(object):
def __init__(self, v=42):
self.val = v
la salida es
$ ./prog.py
foo.Bar
Considere usar el módulo de inspect
que tiene funciones como getmodule
que podría ser lo que está 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''>
Dado que el interés de este tema es obtener nombres completamente calificados, aquí hay una trampa que se produce al usar importaciones relativas junto con el módulo principal existente en el mismo paquete. P.ej:
$ mkdir -p /tmp/fqname/foo
$ touch /tmp/fqname/foo/__init__.py
$ cat<<END > /tmp/fqname/foo/bar.py
> from baz import Baz
> print Baz.__module__
> END
$ cat<<END > /tmp/fqname/foo/baz.py
> class Baz: pass
> END
$ cat <<END > /tmp/fqname/main.py
> import foo.bar
> from foo.baz import Baz
> print Baz.__module__
> END
$ cat <<END > /tmp/fqname/foo/hum.py
> import bar
> import foo.bar
> END
$ PYTHONPATH=/tmp/fqname python /tmp/fqname/main.py
foo.baz
foo.baz
$ PYTHONPATH=/tmp/fqname python /tmp/fqname/foo/bar.py
baz
$ PYTHONPATH=/tmp/fqname python /tmp/fqname/foo/hum.py
baz
foo.baz
Cuando la barra de importación de zumbidos usa la ruta relativa, la barra ve Baz.__module__
como simplemente "baz", pero en la segunda importación que usa nombre completo, bar ve lo mismo que "foo.baz".
Si persiste en nombres completos en alguna parte, es mejor evitar importaciones relativas para esas clases.
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''
Las respuestas proporcionadas no tratan con clases anidadas. Aunque no está disponible hasta Python 3.3 ( PEP 3155 ), realmente quieres usar __qualname__
de la clase. Eventualmente (3.4? PEP 395 ), __qualname__
también existirá para que los módulos se ocupen de los casos donde se cambia el nombre del módulo (es decir, cuando se renombra a __main__
).
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 las clases de object
newstyle.
def get_qualified_python_name_from_class(model):
c = model.__class__.__mro__[0]
name = c.__module__ + "." + c.__name__
return name
__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.