Вивести поточний стек виклику з методу в коді Python


276

Як в 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()

Або для друку до stdout (корисно, якщо ви хочете зберегти перенаправлений вихід разом), використовуйте:

traceback.print_stack(file=sys.stdout)

Але отримати це за допомогою traceback.format_stack()дозволяє робити з ним все, що завгодно.


Як зробити те саме для всіх інших потоків (я кажу про теми, якими я не керую)  ?
користувач2284570

Можливо, мені чогось тут не вистачає, але ви називаєте f, яка є єдиною метою, це викликати g і нічого іншого не робить. Чому
Кріс

6
@Chris: Це просто приклад. Він має кілька функцій, щоб зрозуміти, що 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твердження (і також менш кодування, ніж прийнята відповідь).
martineau

34
traceback.print_exc()друкує трасування стека за будь-яким винятком, з яким ви могли б обробляти, але це не вирішує оригінальне запитання, яке полягає в тому, як надрукувати поточний стек ("де ви зараз", на відміну від "де був ваш код, коли останній виняток пішов вимкнено, якщо є ".)
Том Свірлі


17

Якщо ви використовуєте налагоджувач python, не тільки інтерактивне зондування змінних, але ви можете отримати стек виклику за допомогою команди "where" або "w".

Тож у верхній частині вашої програми

import pdb

Потім у коді, де ви хочете побачити, що відбувається

pdb.set_trace()

і ви потрапляєте в підказку


2
Я програмую в Python вже більше десяти років. Є так багато раз , я міг би використовувати це! Я не можу повірити, що я зараз про це дізнаюся.
hosford42

1
Як це стосується where?
skia.heliou

4
Щоб відповісти на питання "де": Після отримання підказки pdb (pdb) просто введіть whereі він надрукує трасування стека до терміналу.
stephenmm

1
Python 3.7 і вище мають вбудовану функцію, breakpoint()яка унеможливлює імпорт pdb.
користувач650654

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

Написав власну версію декоратора, перш ніж я це побачив. Оголошено.
Сіда Чжоу

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.