Print current call stack from a method in code
Asked Answered
A

8

448

In Python, how can I print the current call stack from within a method (for debugging purposes).

Adair answered 20/7, 2009 at 21:24 Comment(0)
A
497

Here's an example of getting the stack via the traceback module, and printing it:

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():

If you really only want to print the stack to stderr, you can use:

traceback.print_stack()

Or to print to stdout (useful if want to keep redirected output together), use:

traceback.print_stack(file=sys.stdout)

But getting it via traceback.format_stack() lets you do whatever you like with it.

Armillda answered 20/7, 2009 at 21:27 Comment(7)
How to do the same for all other threads (I’m talking about threads I don’t control) ?Proudfoot
Maybe I'm missing something here, but you call f which it's only purpose is here is to call g and does nothing else. WhySip
@Chris: It's just an example. It has multiple functions to make it clear that format_stack() prints all the calls on the stack.Armillda
If you want to get some more verbose output (including vars etc), see this related question, and this one.Quince
@user2284570: You can use sys._current_frames(). E.g. py_better_exchook dump_all_thread_tracebacks does that (disclaimer: I wrote that).Quince
Is there any concern of having production code relying on traceback.format_stack()?Lunge
Why do we need f()? Can't we just call g()?Kowalczyk
S
154
import traceback
traceback.print_stack()
Strophanthin answered 20/7, 2009 at 21:28 Comment(3)
Actually, I like traceback.print_exc() which gives you almost the same thing you would have gotten without the except statement (and is also less coding than the accepted answer).Canfield
traceback.print_exc() prints the stack trace for any exception that you might be handling - but this does not solve the original question, which is how to print the current stack ("where you are now" as opposed to "where your code was when the last exception went off, if any".)Timisoara
It may be useful to limit the trace to a number of entries, e.g.: traceback.print_stack(limit=4)Delaine
C
105

for those who need to print the call stack while using pdb, just do

(Pdb) where
Cassius answered 24/1, 2020 at 10:41 Comment(0)
A
78

inspect.stack() returns the current stack rather than the exception traceback:

import inspect
print inspect.stack()

See https://gist.github.com/FredLoney/5454553 for a log_stack utility function.

Affined answered 24/4, 2013 at 19:37 Comment(1)
Should have much more votes, inspect feels way better to use.Reshape
C
22

If you use python debugger, not only interactive probing of variables but you can get the call stack with the "where" command or "w".

So at the top of your program

import pdb

Then in the code where you want to see what is happening

pdb.set_trace()

and you get dropped into a prompt

Coridon answered 23/10, 2016 at 20:47 Comment(5)
I've been programming in Python for over a decade. There are so many times I could have used this! I can't believe I'm just now finding out about it.Assiduity
How does this relate to where?Valarievalda
To answer the "where" part of the question: After you get the pdb prompt (pdb) just type where and it will print the stack trace to the terminal.Knickerbocker
Python 3.7 and above have a builtin function breakpoint() which obviates the need to import pdb.Santiago
A note for anyone who tries this out in a jupyter notebook: enter exit() into the prompt to get the cell to finish executing.Unwarrantable
C
6

Here's a variation of @RichieHindle's excellent answer which implements a decorator that can be selectively applied to functions as desired. Works with Python 2.7.14 and 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())

Output from sample:

test_func() called:
    File "stacktrace_decorator.py", line 28, in <module>
    print(test_func())
42
Canfield answered 6/2, 2018 at 22:42 Comment(1)
Wrote my own decorator version before I saw this. Upvoted.Iy
S
4

Install Inspect-it

pip3 install inspect-it --user

Code

import inspect;print(*['{:40}| {}:{}\n'.format(x.function, x.filename, x.lineno) for x in inspect.stack()])

you can Make a snippet of this line

it will show you a list of the function call stack with a filename and line number

list from start to where you put this line

Saviour answered 5/7, 2019 at 5:49 Comment(0)
D
0

Use walk_stack method to return to the history stored in the current stack (None):

import traceback
for trace, _ in traceback.walk_stack(None):
    print(trace)
    print(trace.f_locals)
Donnetta answered 12/2 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.