Question

Pour des raisons d'exploitation, je veux récupérer le nom de classe complet d'un objet Python. (Je veux dire avec qualifié le nom de classe, y compris le paquet et le nom du module.)

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

Était-ce utile?

La solution

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 Bar définie comme

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

la sortie est

$ ./prog.py
foo.Bar

Autres conseils

Les réponses fournies ne traitent pas des classes imbriquées. Bien que ce n'est pas disponible jusqu'à Python 3.3 ( PEP 3155 ), vous voulez vraiment utiliser __qualname__ de la classe. Finalement (3.4? PEP 395 ), __qualname__ existera également des modules pour traiter les cas où le module est renommé (quand il est renommé __main__).

Pensez à utiliser le module inspect qui a des fonctions comme getmodule qui pourrait être ce que recherchent:

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

Voici une excellente réponse basée sur Greg Bacon, mais avec quelques contrôles supplémentaires:

__module__ peut être None (selon les docs), et aussi pour un type comme str il peut être __builtin__ (que vous pourriez ne pas vouloir apparaître dans les journaux ou autre). Les contrôles suivants 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 son module est toujours __builtin__)

__module__ ferait l'affaire.

Essayez:

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

Ce site suggère que __package__ pourrait fonctionner pour Python 3.0; Cependant, les exemples donnés, il ne fonctionnera pas sous mon Python 2.5.2 console.

Ceci est un hack mais je soutiens 2.6 et juste besoin de quelque chose simple:

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

'logging.handlers.MemoryHandler'

Certaines personnes (par exemple https://stackoverflow.com/a/16763814/5766934 ) en faisant valoir que __qualname__ 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 aussi correctement pour buildins:

>>> print(full_name_with_qualname(print))
builtins.print
>>> import builtins
>>> builtins.print
<built-in function print>

Pour python3.7 J'utilise:

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

Obtenir:

package.subpackage.ClassName

Depuis l'intérêt de ce sujet est d'obtenir les noms qualifiés, voici un écueil qui se produit lors de l'utilisation des importations par rapport avec le module principal existant dans le même paquet. 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

Lorsque les importations de bourdonnement de barres en utilisant un chemin relatif, bar Sées Baz.__module__ comme juste « baz », mais dans la deuxième importation qui utilise le nom complet, bar voit la même chose que « foo.baz ».

Si vous persistez les noms qualifiés quelque part, il est préférable d'éviter les importations relatives à ces classes.

Aucune des réponses ici travaillé pour moi. Dans mon cas, j'utilisais Python 2.7 et je savais que je serais seulement travailler avec des classes de Newstyle object.

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top