Как мне получить путь к файлу для класса в Python?

99

Учитывая класс C в Python, как я могу определить, в каком файле был определен класс? Мне нужно что-то, что может работать либо с классом C, либо с экземпляром с C.

Причина, по которой я это делаю, заключается в том, что я вообще фанат того, что файлы, которые принадлежат друг другу, находятся в одной папке. Я хочу создать класс, который использует шаблон Django для рендеринга себя как HTML. Базовая реализация должна вывести имя файла для шаблона на основе имени файла, в котором определен класс.

Скажем, я поместил класс LocationArtifact в файл «base / artifacts.py», затем я хочу, чтобы по умолчанию использовалось имя шаблона «base / LocationArtifact.html».

Staale
источник
2
Они предполагают, что вы знаете модуль, который ищете в файле, у меня будет просто строка модуля, поскольку я работаю с реализациями вне класса.
Staale

Ответы:

136

Вы можете использовать модуль проверки , например:

import inspect
inspect.getfile(C.__class__)
DNS
источник
1
Не уверен, что я делал по-другому, но вместо этого getfileя должен был использовать: inspect.getmodule(C.__class__)
AJP
4
Примечание: не работает с классами, созданными пользователем
Daniel Braun
8
Наверное, так и должно быть inspect.getfile(C). Если Cэто класс, то C.__class__ссылается на object, что вызовет исключение TypeError: <module 'builtins' (built-in)> is a built-in class. Я думаю, что только для экземпляра cвы хотите использовать inspect.getfile(c.__class__).
cheshirekow
1
Это не относится к классу, который расширяет абстрактный базовый класс ( metaclass=abc.ABCMeta), поскольку он возвращает /usr/local/lib/python3.7/abc.pyвместо соответствующего файла. Решение @JarretHardie (ниже) сработало лучше.
martian111 08
inspect.getfile (self .__ class__) работал у меня
diman82
37

пытаться:

import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)
Джаррет Харди
источник
1
Для того, чтобы получить путь от экземпляра C (по желанию) OP, замените LocationArtifactс , obj.__class__где OBJ является экземпляром LocationArtifact.
martian111 08
6

Это неправильный подход для Django и действительно форсирование вещей.

Типичный шаблон приложения Django:

  • / проект
    • /Название приложения
      • models.py
      • views.py
      • / шаблоны
        • index.html
        • и т.п.
Совиут
источник
1
+1: Делайте то, что Django делает естественным образом, и жизнь становится намного проще.
S.Lott
1
Согласовано. Django - одна из фреймворков с наименьшим количеством «магии», но шаблоны, теги шаблонов и приложения имеют определенные ожидания как часть своего шаблона. Если вам нужно делать дурацкий вывод классов, вы, вероятно, идете в неправильном направлении.
Soviut