À des fins de journalisation, je souhaite récupérer le nom de classe complet d'un objet Python. (Par qualifié complet, je veux dire le nom de la classe, y compris le nom du paquet et du module.)
Je connais x.__class__.__name__
, mais existe-t-il une méthode simple pour obtenir le paquet et le module?
Avec le programme suivant
#! /usr/bin/env python
import foo
def fullname(o):
# o.__module__ + "." + o.__class__.__qualis 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__.__ # Avoid reporting __builtin__
else:
return module + '.' + o.__class__.__name__
bar = foo.Bar()
print fullname(bar)
et Bar
défini comme
class Bar(object):
def __init__(self, v=42):
self.val = v
la sortie est
$ ./prog.py
foo.Bar
Les réponses fournies ne traitent pas des classes imbriquées. Bien qu'il ne soit pas disponible avant Python 3.3 ( PEP 3155 ), vous voulez vraiment utiliser __qualname__
de la classe. Finalement (3.4? PEP 395 ), __qualname__
existera également pour les modules afin de traiter les cas dans lesquels le module est renommé (c'est-à-dire lorsqu'il est renommé en __main__
).
Pensez à utiliser le module inspect
qui comporte des fonctions telles que getmodule
qui 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'>
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 également pour un type comme str
, il peut s'agir de __builtin__
(que vous ne souhaitez peut-être pas voir apparaître dans les journaux ou autre). Les contrôles suivants vérifient 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 existe peut-être un meilleur moyen de vérifier __builtin__
. Ce qui précède repose simplement sur le fait que str est toujours disponible et que son module est toujours __builtin__
.)
__module__
ferait l'affaire.
Essayer:
>>> import re
>>> print re.compile.__module__
re
Ce site suggère que __package__
pourrait fonctionner pour Python 3.0; Cependant, les exemples donnés ne fonctionneront pas sous ma console Python 2.5.2.
C'est un hack mais je supporte la 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'
Pour python3.7 j'utilise:
".".join([obj.__module__, obj.__name__])
Obtenir:
package.subpackage.ClassName
Étant donné que l’intérêt de cette rubrique est d’obtenir des noms complets, voici un écueil qui se produit lors de l’utilisation des importations relatives avec le module principal existant dans le même package. Par exemple, avec la configuration de 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
Lorsque hum importe bar en utilisant le chemin relatif, bar voit Baz.__module__
comme étant simplement "baz", mais dans la seconde importation qui utilise le nom complet, bar voit la même chose que "foo.baz".
Si vous persistez les noms entièrement qualifiés quelque part, il est préférable d'éviter les importations relatives pour ces classes.
Certaines personnes (par exemple https://stackoverflow.com/a/16763814/5766934 ) soutiennent que __qualname__
est supérieur à __name__
. Voici un exemple montrant 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
Notez que cela fonctionne aussi correctement pour les buildins:
>>> print(full_name_with_qualname(print))
builtins.print
>>> import builtins
>>> builtins.print
<built-in function print>
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 classes newstyle object
.
def get_qualified_python_name_from_class(model):
c = model.__class__.__mro__[0]
name = c.__module__ + "." + c.__name__
return name