Wie erhalte ich den Dateipfad für eine Klasse in Python?

95

Wie kann ich bei einer Klasse C in Python feststellen, in welcher Datei die Klasse definiert wurde? Ich brauche etwas, das entweder in der Klasse C oder in einer Instanz außerhalb von C funktioniert.

Der Grund, warum ich das mache, ist, dass ich im Allgemeinen ein Fan davon bin, Dateien, die zusammen gehören, in denselben Ordner zu legen. Ich möchte eine Klasse erstellen, die eine Django-Vorlage verwendet, um sich selbst als HTML zu rendern. Die Basisimplementierung sollte den Dateinamen für die Vorlage basierend auf dem Dateinamen ableiten, in dem die Klasse definiert ist.

Angenommen, ich habe eine Klasse LocationArtifact in die Datei "base /ifacts.py" eingefügt. Dann möchte ich, dass das Vorlagenname standardmäßig "base / LocationArtifact.html" lautet.

Staale
quelle
2
Diese setzen voraus, dass Sie das Modul kennen, nach dem Sie die Datei suchen. Ich habe nur die Modulzeichenfolge, wenn ich mit Implementierungen außerhalb einer Klasse arbeite.
Staale

Antworten:

130

Sie können das Inspect- Modul folgendermaßen verwenden:

import inspect
inspect.getfile(C.__class__)
DNS
quelle
1
Ich bin mir nicht sicher, was ich anders gemacht habe, aber stattdessen musste getfileich inspect.getmodule(C.__class__)
AJP
4
Hinweis: funktioniert nicht für Klassen, die vom Benutzer erstellt wurden
Daniel Braun
6
Das sollte wohl sein inspect.getfile(C). Wenn Ces sich um eine Klasse handelt, wird C.__class__auf verwiesen object, wodurch eine Ausnahme ausgelöst wird TypeError: <module 'builtins' (built-in)> is a built-in class. Ich denke, dass Sie nur für eine Instanz cverwenden möchten inspect.getfile(c.__class__).
Cheshirekow
1
Dies gilt nicht für eine Klasse, die eine abstrakte Basisklasse ( metaclass=abc.ABCMeta) erweitert, da sie /usr/local/lib/python3.7/abc.pyanstelle der entsprechenden Datei zurückgegeben wird. Die Lösung von @JarretHardie (unten) hat besser funktioniert.
Martian111
36

Versuchen:

import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)
Jarret Hardie
quelle
1
Um den Pfad von einer Instanz von C abzurufen (wie vom OP gewünscht), ersetzen Sie ihn LocationArtifactdurch, obj.__class__wobei obj eine Instanz von LocationArtifact ist.
Martian111
5

Dies ist der falsche Ansatz für Django und erzwingt wirklich Dinge.

Das typische Django-App-Muster lautet:

  • /Projekt
    • /App Name
      • models.py
      • views.py
      • / Vorlagen
        • index.html
        • etc.
Soviut
quelle
1
+1: Mach was Django natürlich macht und das Leben ist so viel einfacher.
S.Lott
1
Einverstanden. Django ist eines der Frameworks mit der geringsten Menge an "Magie", aber Vorlagen, Vorlagen-Tags und Apps haben einige Erwartungen als Teil ihres Musters. Wenn Sie verrückte Klassenschlussfolgerungen machen müssen, gehen Sie wahrscheinlich in die falsche Richtung.
Soviut