2025, Oct 20 04:00

How to Limit pdb's 'where' Output: Use Python's traceback to View a Focused Slice of the Call Stack

Learn to tame Python pdb in deep recursion: limit noisy where output using traceback.print_stack and format_stack to show nearby frames and focus on the bug.

Debugging deep recursion with Python’s pdb can turn a simple question into a wall of noise. The where command dumps the entire call stack, which is great for completeness but not for focus. When the real issue is somewhere around the current frame, you often want just a narrow window around it, not hundreds of frames above and below. There isn’t a built-in way in pdb to limit where output to N surrounding frames, but you can achieve exactly that with the traceback module inside the debugger.

Minimal example that reproduces the problem

The following snippet creates a short call chain that ends in a recursive function. Once the recursion reaches zero, it drops into the debugger. From there, where would list the full stack.

import pdb

def f1():
    f2()


def f2():
    f3()


def f3():
    f4()


def f4():
    go_deep(5)


def go_deep(k):
    if k == 0:
        breakpoint()
    else:
        go_deep(k - 1)

f1()

At the (Pdb) prompt, where will show the entire stack, including frames internal to pdb when breakpoint() is used.

What’s really going on

pdb does not currently provide a function to show only a limited slice of the stack around the current frame. That’s why the output can explode in size during maximum recursion situations. The practical workaround is to use the standard library’s traceback utilities directly from the (Pdb) prompt. You are allowed to import traceback inside pdb and use it to print or format a subset of frames. You can specify a positive limit to show a number of frames relative to the current position, or a negative limit to refer from the top or the bottom of the stack. When breakpoint() is involved, the listing is “polluted” by internal pdb frames; in practice that means bumping your expected number by about ten to compensate.

Solution: use traceback from inside pdb

First, import the module within the debugger session.

(Pdb) import traceback

To print the stack with a limit, use traceback.print_stack. A positive limit prints that many frames, and a negative limit refers from the top or bottom of the stack. Without specifying a frame, the current one is used.

(Pdb) traceback.print_stack()
(Pdb) traceback.print_stack(None, 15)
(Pdb) traceback.print_stack(None, -15)

If the script was started via python -m pdb script.py, you can target the current frame explicitly.

(Pdb) traceback.print_stack(self.curframe, -10)

For finer control and to avoid printing internal debugger frames, format the stack into a list and slice exactly what you need. Then print only that slice, keeping the output clean.

(Pdb) {print(chunk, end='') for chunk in traceback.format_stack()[-30:-10]}

This prints a window of frames without the extra internal calls introduced by breakpoint(). The slicing lets you focus on the “surrounding N levels” near the current position.

Why this matters

When you are hunting a maximum recursion issue, the signal you need is buried under hundreds of frames. Reducing the view to a targeted window shortens the feedback loop and prevents you from scrolling through irrelevant noise. It also works naturally from within pdb, so you don’t have to leave the interactive context where you already have the state available.

Takeaways

If where is overwhelming, switch to the traceback module directly from the (Pdb) prompt. Use traceback.print_stack with positive or negative limits for quick snapshots, or traceback.format_stack with slicing when you want precise control over which frames appear. Keep in mind that breakpoint() adds internal frames; adjust your limits accordingly. If you launched debugging with python -m pdb script.py, pass self.curframe to traceback.print_stack to anchor output to the current frame. This approach keeps your stack view focused on the frames that matter and makes recursion debugging more manageable.

The article is based on a question from StackOverflow by quazgar and an answer by bruno.