Ottieni il nome di classe completo di un oggetto in Python


136

Ai fini della registrazione, desidero recuperare il nome di classe completo di un oggetto Python. (Con qualifica completa intendo il nome della classe incluso il nome del pacchetto e del modulo.)

Lo so x.__class__.__name__, ma esiste un metodo semplice per ottenere il pacchetto e il modulo?

Risposte:


147

Con il seguente programma

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

e Bardefinito come

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

l'uscita è

$ ./prog.py
foo.Bar

2
Questo sembra restituire il modulo in cui è stata definita la barra, non dove è stata definita la barra. Se lo scopo della registrazione è sapere esattamente che tipo di oggetto fosse, allora questo non sembra aiutare.
Mark E. Haase,

È o.__class__.__module__mai diverso da o.__module__?
Larsks,


1
Consiglio vivamente ".".join([o.__module__, o.__name__])Python3
Piotr Pęczek il

A volte non funziona:AttributeError: 'AttributeError' object has no attribute '__module__'
Hendy Irawan il

38

Le risposte fornite non riguardano le classi nidificate. Sebbene non sia disponibile fino a Python 3.3 ( PEP 3155 ), vuoi davvero usare __qualname__la classe. Alla fine (3.4? PEP 395 ), __qualname__esisterà anche che i moduli gestiscano i casi in cui il modulo viene rinominato (cioè quando viene rinominato __main__).


3
Se usi github.com/wbolster/qualname puoi ottenere un equivalente qualname nelle versioni precedenti.
Wouter Bolsterlee,

3
Vale a dire Type.__module__ + '.' + Type.__qualname__.
Kentzo,

4
Con Python 3.6, questo mi dà solo il nome della classe. Non include il modulo.
jpmc26,

2
@ jpmc26 In Python 3.7, __qualname__si risolve ancora solo con il nome della classe
zepp.lee

22

Prendi in considerazione l'uso del inspectmodulo che ha funzioni come quelle getmoduleche potrebbero essere ciò che stai cercando:

>>>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()restituisce oggetti modulo - nomi di classe non completamente qualificati. In effetti, il inspectmodulo non fornisce alcuna funzionalità che possa effettivamente rispondere a questa domanda. Questa risposta è una non risposta. </facepalm>
Cecil Curry,

19

Eccone uno basato sull'ottima risposta di Greg Bacon, ma con un paio di controlli extra:

__module__può essere None(secondo i documenti) e anche per un tipo come strpuò essere __builtin__(che potresti non voler apparire nei registri o altro). I seguenti controlli per entrambe queste possibilità:

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__

(Potrebbe esserci un modo migliore per verificare __builtin__. Quanto sopra si basa solo sul fatto che str è sempre disponibile e il suo modulo è sempre __builtin__)


2
Per salvare gli altri lo sforzo di confrontare le due risposte: il codice nella risposta di Greg Bacon è ora identico al codice in questo, a parte quello Greg ha aggiunto un'istruzione inutile e alcuni commenti sul codice. MB è il vero eroe.
MarredCheese,


9

__module__ farebbe il trucco.

Provare:

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

Questo sito suggerisce che __package__potrebbe funzionare con Python 3.0; Tuttavia, gli esempi forniti non funzioneranno con la mia console Python 2.5.2.


6
Questo è il trucco, grazie! Per il nome completo che userò "%s.%s" % (x.__class__.__module__, x.__class__.__name__)
Hanno S.

7

Questo è un trucco ma sto supportando 2.6 e ho solo bisogno di qualcosa di semplice:

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

'logging.handlers.MemoryHandler'

1
Questo dipende __repr__()dall'implementazione nella classe selezionata ( e dal __str__()non essere sostituito). Inutile nella maggior parte dei casi.
z33k,

7

Alcune persone (ad esempio https://stackoverflow.com/a/16763814/5766934 ) sostengono che __qualname__sia meglio di __name__. Ecco un esempio che mostra la differenza:

$ 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

Nota, funziona anche correttamente per i buildin:

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

2

Poiché l'interesse di questo argomento è quello di ottenere nomi pienamente qualificati, ecco un insulto che si verifica quando si utilizzano le importazioni relative insieme al modulo principale esistente nello stesso pacchetto. Ad esempio, con l'impostazione del modulo seguente:

$ 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

Ecco l'output che mostra il risultato dell'importazione dello stesso modulo in modo diverso:

$ 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

Quando il ronzio importa la barra usando il relativo percorso, la barra vede Baz.__module__solo "baz", ma nella seconda importazione che usa il nome completo, la barra vede lo stesso di "foo.baz".

Se si persistono da qualche parte i nomi completi, è meglio evitare le importazioni relative per quelle classi.


0

Nessuna delle risposte qui ha funzionato per me. Nel mio caso, stavo usando Python 2.7 e sapevo che avrei lavorato solo con le objectclassi newstyle .

def get_qualified_python_name_from_class(model):
    c = model.__class__.__mro__[0]
    name = c.__module__ + "." + c.__name__
    return name
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.