Jak uzyskać ścieżkę do pliku dla klasy w Pythonie?

96

Biorąc pod uwagę klasę C w Pythonie, jak mogę określić, w którym pliku została zdefiniowana klasa? Potrzebuję czegoś, co może działać z klasy C lub z instancji poza C.

Powodem, dla którego to robię, jest to, że generalnie jestem fanem umieszczania plików, które należą do tego samego folderu. Chcę utworzyć klasę, która używa szablonu Django do renderowania się jako HTML. Podstawowa implementacja powinna wywnioskować nazwę pliku dla szablonu na podstawie nazwy pliku, w którym zdefiniowano klasę.

Powiedzmy, że umieściłem klasę LocationArtifact w pliku „base / artifacts.py”, a następnie chcę, aby domyślnym zachowaniem była nazwa szablonu „base / LocationArtifact.html”.

Staale
źródło
2
Zakładają, że znasz moduł, którego szukasz, będę miał po prostu ciąg modułu, gdy pracuję z implementacjami poza klasą.
Staale

Odpowiedzi:

134

Możesz użyć modułu inspekcja , na przykład:

import inspect
inspect.getfile(C.__class__)
DNS
źródło
1
Nie jestem pewien, co robię inaczej, ale zamiast tego getfilemusiałem użyć: inspect.getmodule(C.__class__)
AJP
4
Uwaga: nie działa na zajęciach stworzonych przez użytkownika
Daniel Braun
7
To prawdopodobnie powinno być inspect.getfile(C). Jeśli Cjest klasą, to C.__class__odwołuje się do object, co spowoduje zgłoszenie wyjątku TypeError: <module 'builtins' (built-in)> is a built-in class. Myślę, że tylko na przykład cchcesz użyć inspect.getfile(c.__class__).
cheshirekow
1
Nie dotyczyło to klasy, która rozszerza abstrakcyjną klasę bazową ( metaclass=abc.ABCMeta), ponieważ zwraca ona /usr/local/lib/python3.7/abc.pyzamiast odpowiedniego pliku. Rozwiązanie autorstwa @JarretHardie (poniżej) działało lepiej.
martian111,
inspect.getfile (self .__ class__) pracował dla mnie
diman82
36

próbować:

import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)
Jarret Hardie
źródło
1
Aby uzyskać ścieżkę z przykładu C (zgodnie z życzeniem OP), należy wymienić LocationArtifactw obj.__class__którym obj jest wystąpienie LocationArtifact.
martian111,
5

To jest złe podejście dla Django i naprawdę wymuszające rzeczy.

Typowy wzorzec aplikacji Django to:

  • /projekt
    • /Nazwa aplikacji
      • models.py
      • views.py
      • / templates
        • index.html
        • itp.
Soviut
źródło
1
+1: Rób to, co Django robi naturalnie, a życie jest o wiele prostsze.
S.Lott,
1
Zgoda. Django jest jednym z frameworków z najmniejszą ilością „magii”, ale szablony, tagi szablonów i aplikacje mają pewne oczekiwania jako część swojego wzorca. Jeśli musisz wyciągać zwariowane wnioskowanie klasowe, prawdopodobnie zmierzasz w złym kierunku.
Soviut