#python-3.x #python-importlib
#python-3.x #python-importlib
Вопрос:
Есть хороший способ получить путь к модулю, в котором был определен класс, просто сделайте
inspect.getfile(obj.__class__)
К сожалению, похоже, что он не работает для файлов, загруженных importlib:
spec = importlib.util.spec_from_file_location('loaded_module', module_path)
M = importlib.util.module_from_spec(spec)
spec.loader.exec_module(M)
obj = M.MyClass()
inspect.getfile(obj.__class__)
результаты
File "/nix/store/z65l1jqvxa58zzwwa3bvglb6asj4y8cv-python3-3.8.5/lib/python3.8/inspect.py", line 665, in getfile
raise TypeError('{!r} is a built-in class'.format(object))
TypeError: <class 'loaded_module.MyClass'> is a built-in class
Есть идеи, как это исправить?
Ответ №1:
Ожидается inspect.getfile
, что class
объект (который имеет строковый __module__
атрибут, который является именем модуля) имеет свой модуль в sys.modules
(где модуль можно искать по имени)
без модуля в sys.modules
нем невозможно использовать эту цепочку для поиска вашего файла
чтобы поместить его в sys.modules
, вы должны сделать что-то вроде:
sys.modules[M.__name__] = M
но если у вас есть доступ к M
объекту где-то, вы можете получить доступ .__file__
напрямую, или если у вас есть доступ к loader
в качестве альтернативы, если вы знаете, что для класса в этом файле определен какой-то метод, вы можете запросить объект code этой функции:
>>> M.C.__init__.__code__.co_filename
t.py
Комментарии:
1. Интересно, может быть, я как-то неправильно инициализирую модуль, поэтому он не отображается в sys.modules ?
2. нет, ввод чего
sys.modules
-либо полностью отделен от низкоуровневого механизма importlib. существуют потенциальные проблемы с размещением там вещей (поскольку он глобальный, коллизии имен имеют значение, есть семантика подмодулей и т.д.)3. В идеале я хочу вызвать
inspect.getfile(self.__class__)
внутри конструктора базового класса и получить файл, в котором определен дочерний класс. Но, конечно, у меня есть доступ к загрузчику, поэтому я могу организовать вещи, которые помогутgetfile
на более позднем этапе4. это кажется очень странным дизайном — обычно родительские классы не должны знать о своих подклассах и обычно
inspect
должны использоваться только для отладки5. Хм. Я просто хочу удалить дублирование кода. По сути, каждый модуль описывает своего рода эксперимент, и он должен генерировать журналы в отдельной директории. Схема именования фиксирована и привязана к имени файла модуля. Это очень удобно, потому что позволяет мне просто копировать файлы модуля, переименовывать их, настраивать несколько вещей и готовить модуль к запуску. Поэтому кажется очень логичным перенести эту логику в базовый класс.