Ruft den vollständig qualifizierten Klassennamen eines Objekts in Python ab

136

Zu Protokollierungszwecken möchte ich den vollständig qualifizierten Klassennamen eines Python-Objekts abrufen. (Mit voll qualifiziert meine ich den Klassennamen einschließlich des Paket- und Modulnamens.)

Ich weiß Bescheid x.__class__.__name__, aber gibt es eine einfache Methode, um das Paket und das Modul zu erhalten?

Hanno S.
quelle

Antworten:

147

Mit dem folgenden Programm

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

und Bardefiniert als

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

die Ausgabe ist

$ ./prog.py
foo.Bar
Greg Bacon
quelle
2
Dies scheint das Modul zurückzugeben, in dem der Balken definiert wurde, nicht das, in dem der Balken definiert wurde. Wenn der Zweck der Protokollierung darin besteht, genau zu wissen, um welche Art von Objekt es sich handelt, scheint dies nicht zu helfen.
Mark E. Haase
Ist o.__class__.__module__jemals anders als o.__module__?
Larsks
2
larsks: ja, stackoverflow.com/questions/5271112/…
Yaroslav Bulatov
1
Ich empfehle dringend ".".join([o.__module__, o.__name__])für Python3
Piotr Pęczek
Funktioniert manchmal nicht:AttributeError: 'AttributeError' object has no attribute '__module__'
Hendy Irawan
38

Die angegebenen Antworten beziehen sich nicht auf verschachtelte Klassen. Obwohl es erst in Python 3.3 ( PEP 3155 ) verfügbar ist , möchten Sie __qualname__die Klasse wirklich verwenden . Eventuell (3.4? PEP 395 ) __qualname__wird es auch für Module geben, um Fälle zu behandeln, in denen das Modul umbenannt wird (dh wenn es umbenannt wird __main__).

Nathan Binkert
quelle
3
Wenn Sie github.com/wbolster/qualname verwenden , können Sie bei älteren Versionen einen entsprechenden Qualifikationsnamen erhalten .
Wouter Bolsterlee
3
Dh Type.__module__ + '.' + Type.__qualname__.
Kentzo
4
Mit Python 3.6 gibt mir dies nur den Klassennamen. Das Modul ist nicht enthalten.
jpmc26
2
@ jpmc26 In Python 3.7 wird __qualname__immer noch nur der Klassenname aufgelöst
zepp.lee
22

Erwägen Sie die Verwendung eines inspectModuls mit Funktionen, nach getmoduledenen möglicherweise gesucht wird:

>>>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
quelle
7
inspect.getmodule()Gibt Modulobjekte zurück - nicht vollständig qualifizierte Klassennamen. Tatsächlich bietet das inspectModul keinerlei Funktionen, die diese Frage tatsächlich beantworten würden. Diese Antwort ist keine Antwort. </facepalm>
Cecil Curry
19

Hier ist eine, die auf Greg Bacons ausgezeichneter Antwort basiert, aber mit ein paar zusätzlichen Überprüfungen:

__module__kann sein None(laut den Dokumenten), und auch für einen Typ wie stres sein kann __builtin__(den Sie möglicherweise nicht in Protokollen oder was auch immer erscheinen möchten). Die folgenden Überprüfungen für beide Möglichkeiten:

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__

(Es gibt möglicherweise eine bessere Möglichkeit, dies zu überprüfen __builtin__. Das oben Gesagte beruht lediglich auf der Tatsache, dass str immer verfügbar ist und sein Modul immer verfügbar ist. __builtin__)

MB.
quelle
1
Um anderen die Mühe zu ersparen, die beiden Antworten zu vergleichen: Der Code in Greg Bacons Antwort ist jetzt identisch mit dem Code in dieser, abgesehen davon, dass Greg eine sinnlose else-Anweisung und einige Codekommentare hinzugefügt hat. MB ist der wahre Held.
MarredCheese
11

Für Python3.7 verwende ich:

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

Bekommen:

package.subpackage.ClassName
Prisacari Dmitrii
quelle
Beachten Sie, dass objdies eher eine Klasse als eine Objektinstanz sein muss.
Ivan De Paz Centeno
9

__module__ würde den Trick machen.

Versuchen:

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

Diese Site schlägt vor, dass dies __package__für Python 3.0 funktionieren könnte. Die dort angegebenen Beispiele funktionieren jedoch nicht unter meiner Python 2.5.2-Konsole.

Adam Matan
quelle
6
Das macht den Trick, danke! Für den voll qualifizierten Namen werde ich verwenden "%s.%s" % (x.__class__.__module__, x.__class__.__name__)
Hanno S.
7

Dies ist ein Hack, aber ich unterstütze 2.6 und brauche nur etwas Einfaches:

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

'logging.handlers.MemoryHandler'
Gringo Suave
quelle
1
Dies hängt von der __repr__()Implementierung in der geprüften Klasse ( und auf __str__()nicht in den überschriebenen). In den meisten Fällen nutzlos.
z33k
7

Einige Leute (z. B. https://stackoverflow.com/a/16763814/5766934 ) argumentieren, dass dies __qualname__besser ist als __name__. Hier ist ein Beispiel, das den Unterschied zeigt:

$ 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

Beachten Sie, dass es auch für Buildins korrekt funktioniert:

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

Da das Interesse dieses Themas darin besteht, vollständig qualifizierte Namen zu erhalten, tritt hier eine Gefahr auf, wenn relative Importe zusammen mit dem im selben Paket vorhandenen Hauptmodul verwendet werden. ZB mit dem folgenden Modul-Setup:

$ 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

Hier ist die Ausgabe, die das Ergebnis des unterschiedlichen Imports desselben Moduls zeigt:

$ 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

Wenn Brummen Balken unter Verwendung des relativen Pfads importiert, sieht Balken Baz.__module__nur "baz", aber beim zweiten Import, der den vollständigen Namen verwendet, sieht Balken dasselbe wie "foo.baz".

Wenn Sie die vollständig qualifizierten Namen irgendwo beibehalten, ist es besser, relative Importe für diese Klassen zu vermeiden.

haridsv
quelle
0

Keine der Antworten hier hat bei mir funktioniert. In meinem Fall verwendete ich Python 2.7 und wusste, dass ich nur mit Newstyle- objectKlassen arbeiten würde.

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