Получение имени вызывающего метода в Python без изменений
Быстрый ответ
Чтобы узнать название вызывающего метода изнутри вызываемого, удобно воспользоваться функцией inspect.currentframe()
:
import inspect
def вызываемая_функция():
# Извлечение названия вызывающей функции
print(f"Вызывающая: {inspect.currentframe().f_back.f_code.co_name}")
def вызывающая():
# Осуществляем вызов
вызываемая_функция()
вызывающая()
В итоге мы получаем следующий результат: Вызывающая: вызывающая
. Это приятное и простое решение, типичное для Python.
Альтернативы и подводные камни
Если модуль inspect
не устраивает, можно рассмотреть использование функции sys._getframe()
, однако с внимательностью:
import sys
def вызываемая_функция():
# Выясняем имя вызывающей функции
print(f"Вызывающая: {sys._getframe(1).f_code.co_name}")
def вызывающая():
# Здесь происходит вызов
вызываемая_функция()
вызывающая()
Результат будет таким же, однако, sys._getframe()
— это недокументированная и внутренняя функция, использование её в продакшене может быть сопоставимо с выпуском Джокера на свободу в Готэм.
Состязание в производительности
Помните, что использование inspect.stack()
может существенно увеличить нагрузку на производительность системы:
def вызываемая_функция():
# Можем ли мы быть быстрее?
имя_вызывающей = inspect.stack()[1][3]
# ... продолжение текста ...
Более низкая нагрузка и высокая производительность достигаются при помощи:
def вызываемая_функция():
# Мгновенное получение имени вызывающей функции
имя_вызывающей = inspect.currentframe().f_back.f_code.co_name
# ... здесь продолжается статья ...
Для отладки стоит использовать inspect.stack()
, но в продакшина лучше отдать предпочтение более быстрой currentframe()
.
Особенности работы с памятью: утечки фреймов
Внимание: если стековый фрейм существует слишком долго, это может вызвать утечки памяти. Важно своевременно освобождать ресурсы после получения нужной информации.
Ваш путеводитель по стеку вызовов
Изучение стека вызовов может обеспечить важную информацию:
import inspect
def вызываемая_функция():
# Пропускаем текущий выполняемый контекст
информация_вызывающей = inspect.stack()[1]
# Извлекаем необходимые данные
название_функции, название_файла, номек_строки, назание_метода, контекст_кода, индекс = информация_вызывающей
print(f"Функция '{название_метода}' была вызвана в строке {номек_строки} из файла '{название_файла}'.")
Таким подходом можно получить более полную информацию о контексте вызывающей функции, нежели просто её имя.
Визуализация
Представьте, что прослеживание названия вызывающей функции – это что-то вроде расследования в детективной истории.
Среди слоёв кода прячется уклончивый метод:
def вызываемая_функция():
...
Детектив достаёт лупу:
import inspect
def вызываемая_функция():
имя_вызывающего = inspect.stack()[1].function
return f"Меня вызвала... {имя_вызывающего}!"
И тайна всё ближе к разгадке:
"Мы нашли имя уклончивой функции — 📜 call_me_maybe
!"
Путь вызывающей функции становится яснен:
Стек вызовов:
- 🌟main_function🌟
- helper_function
- 👀call_me_maybe👀
След за следом, солнце садится, тайна разгадана! 🎯
Варианты: разные контексты
Классы и модули
С методами классов и модулями всё становится слегка сложнее:
class MyClass:
def метод_один(self):
# Запускаем метод_два
self.метод_два()
def метод_два(self):
print(f"Меня вызвал: {inspect.stack()[1][3]}")
экземпляр = MyClass()
экземпляр.метод_один()
Пример демонстрирует, что метод_один
инициирует вызов метод_два
.
Безымянные вызовы
С безымянными функциями, такими как лямбды:
(lambda: вызываемая_функция())()
inspect.stack()[1][3]
вернёт '<lambda>'
, обеспечивая возможность отследить даже анонимные вызовы.
Вызовы из главного блока
Многим функциям необходимо знать, были ли они вызваны из главного блока:
if __name__ == '__main__':
def вызываемая_функция():
print("Функция вызвана из главного блока вызовов.")
вызываемая_функция()
Этот код указывает, осуществлен ли вызов непосредственно из главной программы.
Полезные материалы
- inspect — Исследование живых объектов — Документация Python 3.12.2 — Детализированная информация о модуле
inspect
. - 3. Модель данных — Документация Python 3.12.2 — Глубокий анализ фреймов и объектов в Python.
- Как пользоваться модулем logging — Документация Python 3.12.2 — Руководство по записи информации о вызовах в лог-файлы.
- traceback — Печать или извлечение трассировки стека — Документация Python 3.12.2 — Инструкция о трассировках для отладки.
- Понимание Python Traceback – Real Python — Описание трассировок стека от Real Python.
- Исключительные Исключения – Доклад на PyCon от Марио Корчеро — Обсуждение исключений и трассировок стека на конференции PyCon.
- Встроенные функции Python | Programiz — Описывается функция
inspect.stack()
на ресурсе Programiz.