Obtenir le nom de classe complet d'un objet en Python

136

À des fins de journalisation, je souhaite récupérer le nom de classe complet d'un objet Python. (Avec pleinement qualifié, je veux dire le nom de la classe, y compris le nom du package et du module.)

Je sais x.__class__.__name__, mais existe-t-il une méthode simple pour obtenir le package et le module?

Hanno S.
la source

Réponses:

147

Avec le programme suivant

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

et Bardéfini comme

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

la sortie est

$ ./prog.py
foo.Bar
Greg Bacon
la source
2
Cela semble renvoyer le module où la barre a été définie, pas où la barre a été définie. Si le but de la journalisation est de savoir exactement de quel type d'objet il s'agissait, cela ne semble pas aider.
Mark E. Haase
Est-ce que o.__class__.__module__jamais différent de o.__module__?
larsks
2
larsks: oui, stackoverflow.com/questions/5271112/…
Yaroslav Bulatov
1
Je recommande fortement ".".join([o.__module__, o.__name__])Python3
Piotr Pęczek
Ne fonctionne pas parfois:AttributeError: 'AttributeError' object has no attribute '__module__'
Hendy Irawan
38

Les réponses fournies ne concernent pas les classes imbriquées. Bien que ce ne soit pas disponible avant Python 3.3 ( PEP 3155 ), vous voulez vraiment utiliser __qualname__la classe. Finalement (3.4? PEP 395 ), __qualname__existera également pour les modules pour traiter les cas où le module est renommé (c'est-à-dire lorsqu'il est renommé en __main__).

Nathan Binkert
la source
3
Si vous utilisez github.com/wbolster/qualname, vous pouvez obtenir un équivalent qualname sur les anciennes versions.
wouter bolsterlee
3
Ie Type.__module__ + '.' + Type.__qualname__.
Kentzo
4
Avec Python 3.6, cela ne me donne que le nom de la classe. Il n'inclut pas le module.
jpmc26
2
@ jpmc26 Dans Python 3.7, __qualname__ne résout toujours que le nom de la classe
zepp.lee
22

Pensez à utiliser le inspectmodule qui a des fonctions comme celles getmodulequi pourraient être ce que vous recherchez:

>>>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'>
Tendayi Mawushe
la source
7
inspect.getmodule()renvoie des objets de module - des noms de classe non qualifiés. En fait, le inspectmodule ne fournit aucune fonctionnalité qui répondrait réellement à cette question. Cette réponse est une non-réponse. </facepalm>
Cecil Curry
19

En voici une basée sur l'excellente réponse de Greg Bacon, mais avec quelques vérifications supplémentaires:

__module__peut être None(selon la documentation), et aussi pour un type comme stril peut l'être __builtin__(que vous ne voudrez peut-être pas voir apparaître dans les journaux ou autre). Les vérifications suivantes pour ces deux possibilités:

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__

(Il pourrait y avoir une meilleure façon de vérifier __builtin__. Ce qui précède repose simplement sur le fait que str est toujours disponible et que son module l'est toujours __builtin__)

MB.
la source
2
Pour épargner aux autres l'effort de comparer les deux réponses: le code de la réponse de Greg Bacon est maintenant identique au code de celui-ci, à part cela Greg a ajouté une instruction else inutile et quelques commentaires de code. MB est le vrai héros.
MarredCheese
11

Pour python3.7 j'utilise:

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

Obtenir:

package.subpackage.ClassName
Prisacari Dmitrii
la source
notez qu'il objdoit s'agir d'une classe plutôt que d'une instance d'objet.
Ivan De Paz Centeno le
9

__module__ ferait l'affaire.

Essayer:

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

Ce site suggère que cela __package__pourrait fonctionner pour Python 3.0; Cependant, les exemples qui y sont donnés ne fonctionneront pas sous ma console Python 2.5.2.

Adam Matan
la source
6
Cela fait l'affaire, merci! Pour le nom complet que j'utiliserai "%s.%s" % (x.__class__.__module__, x.__class__.__name__)
Hanno S.
7

C'est un hack mais je supporte 2.6 et j'ai juste besoin de quelque chose de simple:

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

'logging.handlers.MemoryHandler'
Gringo Suave
la source
1
Cela dépend de l' __repr__()implémentation dans la classe vérifiée ( et du fait de __str__()ne pas être surchargée). Inutile dans la plupart des cas.
z33k
7

Certaines personnes (par exemple https://stackoverflow.com/a/16763814/5766934 ) soutiennent que __qualname__c'est mieux que __name__. Voici un exemple qui montre la différence:

$ 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

Remarque, cela fonctionne également correctement pour les buildins:

>>> print(full_name_with_qualname(print))
builtins.print
>>> import builtins
>>> builtins.print
<built-in function print>
Christoph Böddeker
la source
2

L'intérêt de cette rubrique étant d'obtenir des noms complets, voici un piège qui se produit lors de l'utilisation d'importations relatives avec le module principal existant dans le même package. Par exemple, avec la configuration du module ci-dessous:

$ 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

Voici la sortie montrant le résultat de l'importation du même module différemment:

$ 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

Quand hum importe la barre en utilisant le chemin relatif, bar voit Baz.__module__simplement "baz", mais dans la seconde importation qui utilise le nom complet, bar voit la même chose que "foo.baz".

Si vous conservez les noms complets quelque part, il est préférable d'éviter les importations relatives pour ces classes.

haridsv
la source
0

Aucune des réponses ici n'a fonctionné pour moi. Dans mon cas, j'utilisais Python 2.7 et je savais que je ne travaillerais qu'avec des objectclasses newstyle .

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