it-swarm.com.de

Holen Sie sich einen vollständig qualifizierten Klassennamen eines Objekts in Python

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

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

102
Hanno S.

Mit folgendem Programm

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

und Bar definiert als

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

die Ausgabe ist

$ ./prog.py
foo.Bar
112
Greg Bacon

Die bereitgestellten Antworten beziehen sich nicht auf verschachtelte Klassen. Obwohl es nicht bis Python 3.3 ( PEP 3155 ) verfügbar ist, möchten Sie wirklich __qualname__ der Klasse verwenden. Irgendwann (3,4? PEP 395 ) wird auch __qualname__ für Module existieren, um Fälle zu behandeln, in denen das Modul umbenannt wird (d. H. Wenn es in __main__ umbenannt wird).

23
Nathan Binkert

Erwägen Sie die Verwendung des Moduls inspect, das Funktionen wie getmodule enthält, nach denen 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'>
21
Tendayi Mawushe

Hier ist eine von Greg Bacons exzellente Antwort, aber mit ein paar zusätzlichen Prüfungen:

__module__ kann None sein (entsprechend den Dokumenten), und auch für einen Typ wie str kann es __builtin__ sein (was Sie möglicherweise nicht in Protokollen oder was auch immer anzeigen möchten). Die folgenden beiden Möglichkeiten werden geprüft:

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__

(Möglicherweise gibt es eine bessere Möglichkeit, nach __builtin__ zu suchen. Das Obige beruht nur auf der Tatsache, dass str immer verfügbar ist, und sein Modul ist immer __builtin__.)

13
MB.

__module__ würde den Trick tun.

Versuchen:

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

Diese Site schlägt vor, dass __package__ für Python 3.0 funktionieren könnte; Die dort aufgeführten Beispiele funktionieren jedoch nicht unter meiner Python 2.5.2-Konsole.

9
Adam Matan

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'
5
Gringo Suave

Für Python3.7 verwende ich:

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

Bekommen:

package.subpackage.ClassName
4

Da es in diesem Thema darum geht, vollständig qualifizierte Namen zu erhalten, ist hier ein Fallstrick, der auftritt, wenn relative Importe zusammen mit dem im selben Paket vorhandenen Hauptmodul verwendet werden. Zum Beispiel mit der folgenden Moduleinstellung:

$ 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 Importierens desselben Moduls anders 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 ein Brumm-Balken mit einem relativen Pfad importiert wird, sieht der Balken Baz.__module__ nur als "baz", aber beim zweiten Import, der den vollständigen Namen verwendet, sieht der Balken dasselbe wie "foo.baz".

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

2
haridsv

Einige Leute (z. B. https://stackoverflow.com/a/16763814/5766934 ) argumentieren, dass __qualname__ besser ist als __name__.

$ 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>
1

Keine der Antworten funktionierte für mich. In meinem Fall benutzte ich Python 2.7 und wusste, dass ich nur mit newstyle object-Klassen arbeiten würde. 

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