Frage

Für Protokollierungszwecke möchte ich den vollständig qualifizierten Klassennamen eines Python-Objekt abzurufen. (Mit voll qualifizieren meine ich die Klassennamen einschließlich der Verpackung und Modulnamen.)

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

War es hilfreich?

Lösung

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 Bar definiert als

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

ist der Ausgang

$ ./prog.py
foo.Bar

Andere Tipps

Die bereitgestellten Antworten Sie befasst sich nicht mit verschachtelten Klassen. Obwohl es bis Python nicht verfügbar ist 3.3 ( PEP 3155 ), wollen Sie wirklich verwenden __qualname__ der Klasse. Schließlich (3.4? PEP 395 ), __qualname__ auch für Module existieren, zu beschäftigen Fälle, in denen das Modul umbenannt wird (dh, wenn es um __main__ umbenannt wird).

Betrachten Sie das inspect Modul, das Funktionen wie getmodule hat das, was suchen werden:

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

Hier ist ein auf Basis von Greg Bacons ausgezeichnete Antwort, aber mit ein paar zusätzlichen Kontrollen:

__module__ kann (nach der docs) None wird, und auch für einen Typen wie str kann es __builtin__ werden (die Sie nicht in Protokollen erscheinen möchten oder was auch immer). Die folgenden Kontrollen für beide dieser 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 könnte eine bessere Möglichkeit für __builtin__ zu überprüfen. Die oben verlassen sich nur auf der Tatsache, dass str immer verfügbar ist, und sein Modul ist immer __builtin__)

__module__ würde den Trick tun.

Versuchen:

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

Diese Seite dass __package__ schlägt vor, für Python 3.0 funktionieren könnte; Doch angesichts der Beispiele wird es nicht unter meiner Python 2.5.2 Konsole arbeiten.

Dies ist ein Hack, aber ich bin 2.6 unterstützen und braucht nur etwas einfach:

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

'logging.handlers.MemoryHandler'

Einige Leute (zB https://stackoverflow.com/a/16763814/5766934 ), dass __qualname__ streiten ist besser 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, es funktioniert auch richtig für buildins:

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

Für python3.7 ich benutze:

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

Ankommen:

package.subpackage.ClassName

Da das Interesse an diesem Thema voll qualifizierte Namen zu bekommen ist, ist hier eine Gefahr, die auftritt, wenn die relativen Einfuhren mit zusammen mit dem Hauptmodul im selben Paket vorhanden ist. Zum Beispiel mit den folgenden Moduleinstellungen:

$ 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 das Ergebnis des Imports das gleiche Modul zeigt anders:

$ 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 hum Importe bar relativen Pfad, Bar sieht als nur "baz" Baz.__module__, aber in dem zweiten Import, die vollständigen Namen verwendet, eine Bar sieht das gleiche wie "foo.baz".

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

Keine der Antworten hier für mich gearbeitet. In meinem Fall war ich Python 2.7 und wusste, dass ich mit 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top