Это основано на ответе @ mouad, но стало более полезным (IMO), включив на каждом уровне имя файла (но не его полный путь) и номер строки стека вызовов, и оставив этот стек в самом недавно вызванном-из (то есть НЕ в обратном порядке), потому что я так хочу это прочитать: -)
Каждая запись имеет file: line: func (), которая является той же последовательностью, что и обычная трассировка стека, но все ната же строка намного более компактна.
import inspect
def callers(self):
caller_list = []
frame = inspect.currentframe()
while frame.f_back:
caller_list.append('{2}:{1}:{0}()'.format(frame.f_code.co_name,frame.f_lineno,frame.f_code.co_filename.split("\\")[-1]))
frame = frame.f_back
callers = ' <= '.join(caller_list)
return callers
Вам может понадобиться добавить дополнительный f_back, если у вас есть какие-то промежуточные вызовы для создания текста журнала.
frame = inspect.currentframe().f_back
Выводит примерно так:
file2.py:620:func1() <= file3.py:211:func2() <= file3.py:201:func3() <= main.py:795:func4() <= file4.py:295:run() <= main.py:881:main()
Мне нужна эта трассировка стека только в двух ключевых функциях, поэтому я добавляю вывод вызывающих в текст в вызове logger.debug (), например, htis:
logger.debug("\nWIRE: justdoit request -----\n"+callers()+"\n\n")