Получить путь импорта функции

from pack.mod import f

Как получить от объекта f информацию об импорте - 'pack.mod'

Я могу получить его с помощью f.__module__ но если функция def в модуле, где я получаю этот атрибут (f.__module__), он возвращает '__main__'. Но мне нужен реальный путь здесь - 'pack.mod'

Я нашел этот способ для получения этой информации:

inspect.getmodule(f).__file__

тогда я могу запустить путь запуска из sys.path, заменить / на . и получить путь как - 'pack.mod' Но может существовать еще более удобный способ?

Ответ 1

Что inspect.getmodule(f) делает внутренне, за sources.py источники, по существу sys.modules.get(object.__module__) - я бы не вызвал использование этого кода прямо "более удобно", хотя (кроме "по существу" части, inspect имеет много полезного лова и исправления угловых случаев).

Почему бы не позвонить напрямую проверить .getsourcefile(f)?

Изменить: чтение между строками, которые, по-видимому, OP пытается сделать что-то вроде

python /foo/bar/baz/bla.py

и внутри bla.py (который, таким образом, выполняется как __main__), определяет "что оператор from или import мог использовать другой основной script для импорта этой функции изнутри меня?".

Проблема в том, что вопрос неуместен, потому что не может быть любой такой путь, который можно использовать для этой цели (ничто не гарантирует, что текущий основной путь script находится на sys.path, когда этот main script запускается позже), может быть несколько разных (например, как /foo/bar, так и /foo/bar/baz могут находиться на sys.path и /foo/bar/baz/__init__.py, и в этом случае from baz.bla import f и from bla import f могут работать), и ничто не гарантирует, что какой-то другой предыдущий элемент sys.path не может "упредить" попытку импорта (например, /foo/bar/baz находится на sys.path, но перед ним там также /fee/fie/foo и полностью несвязанный файл /fee/fie/foo/bla.py также существует и т.д.).

Какова бы ни была цель такого рода попыток обнаружения, я предлагаю найти альтернативную архитектуру, например, ту, где from baz.bla import f выполняется (как говорит OP в начале вопроса), так что f.__module__ правильно установлено на baz.bla.

Ответ 2

Вы хотите атрибут __name__ от __module__:

In [16]: import inspect
In [17]: inspect.getmodule(MyObject).__name__
Out[17]: 'lib.objects.MyObject'