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?

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

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


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


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

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


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


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.


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'

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>

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.


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.