Comment obtenir le chemin de fichier d'une classe en Python?

95

Étant donné une classe C en Python, comment puis-je déterminer dans quel fichier la classe a été définie? J'ai besoin de quelque chose qui puisse fonctionner à partir de la classe C ou d'une instance hors C.

La raison pour laquelle je fais cela, c'est parce que je suis généralement fan de mettre des fichiers qui appartiennent ensemble dans le même dossier. Je veux créer une classe qui utilise un modèle Django pour se rendre au format HTML. L'implémentation de base doit déduire le nom de fichier du modèle en fonction du nom de fichier dans lequel la classe est définie.

Disons que je mets une classe LocationArtifact dans le fichier "base / artifacts.py", puis je veux que le comportement par défaut soit que le nom du modèle soit "base / LocationArtifact.html".

Staale
la source
2
Ceux-ci supposent que vous connaissez le module pour lequel vous recherchez le fichier, j'aurai juste la chaîne du module car je travaille avec des implémentations d'une classe.
Staale

Réponses:

130

Vous pouvez utiliser le module inspect , comme ceci:

import inspect
inspect.getfile(C.__class__)
DNS
la source
1
Je ne sais pas ce que je faisais de différent, mais au lieu de cela, getfilej'ai dû utiliser: inspect.getmodule(C.__class__)
AJP
4
Remarque: ne fonctionne pas sur une classe créée par l'utilisateur
Daniel Braun
6
Cela devrait probablement être inspect.getfile(C). Si Cest une classe, alors C.__class__fait référence à object, ce qui déclenchera une exception TypeError: <module 'builtins' (built-in)> is a built-in class. Je pense que cvous ne souhaitez utiliser que pour une instance inspect.getfile(c.__class__).
cheshirekow
1
Cela n'a pas été le cas pour une classe qui étend une classe de base abstraite ( metaclass=abc.ABCMeta), car elle renvoie à la /usr/local/lib/python3.7/abc.pyplace du fichier approprié. La solution de @JarretHardie (ci-dessous) fonctionnait mieux.
martian111
36

essayer:

import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)
Jarret Hardie
la source
1
Pour obtenir le chemin à partir d'une instance de C (comme souhaité par l'OP), remplacez LocationArtifactpar obj.__class__où obj est une instance de LocationArtifact.
martian111
5

C'est la mauvaise approche pour Django et force vraiment les choses.

Le modèle d'application Django typique est:

  • /projet
    • /nom de l'application
      • models.py
      • views.py
      • / modèles
        • index.html
        • etc.
Soviut
la source
1
+1: Faites ce que Django fait naturellement et la vie est tellement plus simple.
S.Lott
1
D'accord. Django est l'un des frameworks avec le moins de «magie», mais les modèles, les balises de modèle et les applications ont des attentes dans le cadre de leur modèle. Si vous devez faire des inférences de classe farfelues, vous allez probablement dans la mauvaise direction.
Soviut