Конечно же первое что приходит в голову это traceback.print_stack(). Но мне не нравится его многословное форматирование. Поэтому я решил сделать свой аналог.
Делается это совсем не сложно, достаточно посмотреть как работает функция print_stack() и сделать аналогично. Все дополнительные функции уже имеются в модуле traceback.
Первым делом достаём фрейм
frame = sys._getframe().f_backТеперь преобразуем его в стек вызовов
stack = traceback.extract_stack(frame)
Теперь у нас есть список инстансов класса FrameSummary в порядке их вызова. Остаётся сделать выводfor item in stack:Получается что-то вроде такого
print(f"{os.path.basename(item.filename)}[{item.lineno}] -> {item.name}")
__main__.py[123] -> <module>Как можно улучшить?
module1.py[456] -> func1
module2.py[789] -> func2
🔸 Фильтр по имени файла.
Удобно при работе через дебагер, например, в Pycharm. Пропускаются ненужные вызовы.
🔸 Выводить передаваемые аргументы.
Придется сделать свой extract_stack.
🔸 Добавить цвета
Пример реализации здесь. Просто вызовите эту функцию в том месте где требуется увидеть цепочку вызовов.
PS. Да, я знаю на сколько это странный способ дебага. Но такой инструмент потребовался под конкретную ситуацию и он справился хорошо.
PPS:
А теперь суровый хардкод! Всё в одну строку плюс некоторые дополнения в форматировании! (не повторяйте это дома!)
print_stack_simple = lambda: print(*[f"{' ' * i}{os.path.basename(item.filename)}[{item.lineno}] -> {item.name}{'()' if not '>' in item.name else ''}" for i, item in enumerate(traceback.extract_stack(sys._getframe().f_back)[:-1])], sep='\n')
#tricks