For what it's worth, I made a Python package that lets you combine both approaches:
https://github.com/breuleux/breakword. You run your program once to print out what's going on, but it also displays a unique word next to each line and on a second run you can set a breakpoint at any of these words to investigate deeper. It's pretty handy when you spot an issue at the hundredth invocation of some function deep in the program's execution.