Como obtenho o caminho do arquivo para uma classe em Python?

95

Dada uma classe C em Python, como posso determinar em qual arquivo a classe foi definida? Preciso de algo que possa funcionar na classe C ou em uma instância da C.

Estou fazendo isso porque geralmente sou fã de colocar arquivos que pertencem juntos na mesma pasta. Eu quero criar uma classe que usa um modelo Django para renderizar a si mesmo como HTML. A implementação básica deve inferir o nome do arquivo para o modelo com base no nome do arquivo em que a classe está definida.

Digamos que eu coloque uma classe LocationArtifact no arquivo "base / artifacts.py", então quero que o comportamento padrão seja o nome do modelo "base / LocationArtifact.html".

Staale
fonte
2
Eles presumem que você conhece o módulo para o qual está procurando o arquivo. Terei apenas a string do módulo enquanto trabalho com as implementações de uma classe.
Staale

Respostas:

130

Você pode usar o módulo inspect , assim:

import inspect
inspect.getfile(C.__class__)
DNS
fonte
1
Não tenho certeza do que estava fazendo diferente, mas em vez de getfileusar: inspect.getmodule(C.__class__)
AJP
4
Nota: não funciona em classes criadas pelo usuário
Daniel Braun
6
Provavelmente deveria ser inspect.getfile(C). Se Cfor uma classe, então C.__class__se refere a object, o que gerará uma exceção TypeError: <module 'builtins' (built-in)> is a built-in class. Eu acho que apenas para uma instância cque você deseja usar inspect.getfile(c.__class__).
cheshirekow
1
Isso não acontecia com uma classe que estende uma classe base abstrata ( metaclass=abc.ABCMeta), pois ela retorna em /usr/local/lib/python3.7/abc.pyvez do arquivo apropriado. A solução de @JarretHardie (abaixo) funcionou melhor.
martian111
36

experimentar:

import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)
Jarret Hardie
fonte
1
Para obter o caminho de uma instância de C (conforme desejado pelo OP), substitua LocationArtifactpor obj.__class__onde obj é uma instância de LocationArtifact.
martian111
5

Esta é a abordagem errada para Django e realmente forçando as coisas.

O padrão típico de aplicativo Django é:

  • /projeto
    • /nome do aplicativo
      • models.py
      • views.py
      • /modelos
        • index.html
        • etc.
Soviut
fonte
1
+1: Faça o que Django faz naturalmente e a vida ficará muito mais simples.
S.Lott
1
Acordado. Django é um dos frameworks com a menor quantidade de "mágica", mas templates, tags de template e aplicativos têm algumas expectativas como parte de seu padrão. Se você está tendo que fazer inferências malucas de classe, provavelmente está indo na direção errada.
Soviut