Вывести текущий стек вызовов из метода в коде Python


Ответы:


319

Вот пример получения стека через модуль traceback и его печати:

import traceback

def f():
    g()

def g():
    for line in traceback.format_stack():
        print(line.strip())

f()

# Prints:
# File "so-stack.py", line 10, in <module>
#     f()
# File "so-stack.py", line 4, in f
#     g()
# File "so-stack.py", line 7, in g
#     for line in traceback.format_stack():

Если вы действительно хотите распечатать стек в stderr, вы можете использовать:

traceback.print_stack()

Или для печати в стандартный вывод (полезно, если вы хотите сохранить перенаправленный вывод вместе), используйте:

traceback.print_stack(file=sys.stdout)

Но получение этого traceback.format_stack()позволяет делать с ним все, что угодно.


Как сделать то же самое для всех других потоков (я говорю о потоках, которые я не контролирую)  ?
— user2284570

Может быть, я что-то здесь упускаю, но вы называете f, единственная цель которой здесь, это вызвать g и больше ничего не делает. Почему
— Крис

6
@ Крис: Это просто пример. Он имеет несколько функций, чтобы было ясно, что format_stack () печатает все вызовы в стеке.
— RichieHindle

Если вы хотите получить более подробный вывод (включая vars и т. Д.), Посмотрите этот связанный вопрос и этот .
— Альберт

@ user2284570: Вы можете использовать sys._current_frames(). Например, py_better_exchookdump_all_thread_tracebacks делает это (отказ от ответственности: я это написал).
— Альберт

93
import traceback
traceback.print_stack()

8
На самом деле, мне нравится, traceback.print_exc()что дает вам почти то же самое, что вы получили бы без exceptутверждения (и также менее кодирующе, чем принятый ответ).
— Мартино

34
traceback.print_exc()печатает трассировку стека для любого исключения, которое вы, возможно, обрабатываете - но это не решает первоначальный вопрос, а именно, как напечатать текущий стек («где вы сейчас находитесь», а не «где был ваш код, когда было последнее исключение»). выкл, если есть ".)
— Том Свирли


17

Если вы используете отладчик Python, не только интерактивное исследование переменных, но вы можете получить стек вызовов с помощью команды «где» или «w».

Так что в верхней части вашей программы

import pdb

Затем в коде, где вы хотите увидеть, что происходит

pdb.set_trace()

и вы попадете в подсказку


2
Я программирую на Python более десяти лет. Есть так много раз , я мог бы использовать это! Я не могу поверить, что только сейчас узнаю об этом.
— hosford42

1
Как это связано с where?
— skia.heliou

4
Чтобы ответить на вопрос «где»: после того, как вы получите приглашение pdb, (pdb) просто наберите, whereи он выведет трассировку стека на терминал.
— Стивенм

1
Python 3.7 и выше имеют встроенную функцию, breakpoint()которая устраняет необходимость импорта pdb.
— user650654

6

для тех, кому нужно распечатать стек вызовов при использовании pdb, просто сделайте

(Pdb) where

2

Вот вариант отличного ответа @ RichieHindle, в котором реализован декоратор, который можно выборочно применять к функциям по желанию. Работает с Python 2.7.14 и 3.6.4.

from __future__ import print_function
import functools
import traceback
import sys

INDENT = 4*' '

def stacktrace(func):
    @functools.wraps(func)
    def wrapped(*args, **kwds):
        # Get all but last line returned by traceback.format_stack()
        # which is the line below.
        callstack = '\n'.join([INDENT+line.strip() for line in traceback.format_stack()][:-1])
        print('{}() called:'.format(func.__name__))
        print(callstack)
        return func(*args, **kwds)

    return wrapped

@stacktrace
def test_func():
    return 42

print(test_func())

Выход из образца:

test_func() called:
    File "stacktrace_decorator.py", line 28, in <module>
    print(test_func())
42

Написал свой собственный вариант декоратора, прежде чем я увидел это. Upvoted.
— Сида Чжоу

0

Установите Inspect-it

pip3 install inspect-it --user

Код

import inspect;print(*['\n\x1b[0;36;1m| \x1b[0;32;1m{:25}\x1b[0;36;1m| \x1b[0;35;1m{}'.format(str(x.function), x.filename+'\x1b[0;31;1m:'+str(x.lineno)+'\x1b[0m') for x in inspect.stack()])

Вы можете сделать фрагмент этой строки

он покажет вам список стека вызовов функций с именем файла и номером строки

список от начала, где вы положили эту строку

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.