How do I skip a loop with pdb? - python

How can I skip over a loop using pdb.set_trace()?
For example,
pdb.set_trace()
for i in range(5):
print(i)
print('Done!')
pdb prompts before the loop. I input a command. All 1-5 values are returned and then I'd like to be prompted with pdb again before the print('Done!') executes.

Try the until statement.
Go to the last line of the loop (with next or n) and then use until or unt. This will take you to the next line, right after the loop.
http://www.doughellmann.com/PyMOTW/pdb/ has a good explanation

You should set a breakpoint after the loop ("break main.py:4" presuming the above lines are in a file called main.py) and then continue ("c").

In the link mentioned by the accepted answer (https://pymotw.com/3/pdb/), I found this section somewhat more helpful:
To let execution run until a specific line, pass the line number to
the until command.
Here's an example of how that can work re: loops:
It spares you from two things: having to create extra breakpoints, and having to navigate to the end of a loop (especially when you might have already iterated such that you wouldn't be able to without re-running the debugger).
Here's the Python docs on until. Btw I'm using pdb++ as a drop-in for the standard debugger (hence the formatting) but until works the same in both.

You can set another breakpoint after the loop and jump to it (when debugging) with c:
pdb.set_trace()
for i in range(5):
print(i)
pdb.set_trace()
print('Done!')

If I understood this correctly.
One possible way of doing this would be:
Once you get you pdb prompt . Just hit n (next) 10 times to exit the loop.
However, I am not aware of a way to exit a loop in pdb.
You could use r to exit a function though.

Related

Python Unusual error with multiline code in IDLE Shell

I was testing some code on IDLE for Python which I haven't used in a while and stumbled on an unusual error.
I was attempting to run this simple code:
for i in range(10):
print(i)
print('Done')
I recall that the shell works on a line by line basis, so here is what I did first:
>>> for i in range(10):
print(i)
print('Done')
This resulted in a indent error, shown by the picture below:
I tried another way, as it might be that the next statement needed to be at the start perhaps, like this:
>>> for i in range(10):
print(i)
print('Done')
But this gave a syntax error, oddly:
This is quite odd to me the way IDLE works.
Take Note:
I am actually testing a much more complex program and didn't want to create a small Python file for a short test. After all, isn't IDLE's shell used for short tests anyways?
Why is multi-line coding causing this issue? Thanks.
Just hit return once or twice after the print(i), until you get the >>> prompt again. Then you can type the print('Done'). What's going on is that python is waiting for you to tell it that you're done working inside that for. And you do that by hitting return.
(You'll see, though, that the for loop is executed right away.)

Why does Python not print what I ask it to print while in a loop?

I have a code where I iterate a certain scheme using a loop. At each iteration I want a printout of what happened. A silly minimal working example is shown below:
import time
Iter=0
for k in range(1,10):
Iter=Iter+1
print('At iteration ',Iter,': k=',k,'.',sep='')
time.sleep(1)
The time.sleep(1) is there to make my problem visible for such a short iteration scheme: At each iteration, the print() function only prints the first string. The rest appears only after the print() function is called in the next iteration. If I use the exact same syntax for the print() function outside of the loop, then I obtain the output I want. How can I get the same output when I'm inside the loop?
I'm new at this, but I suspect it could be relevant that I use the Anaconda3 (64-bit) distribution of Python 3.5 with the Spyder IDE on a Win10 machine.
Edit 1: SOLVED using the suggestion by #RemcoGerlich: "Try adding 'import sys' and then after the print sys.stdout.flush()." Many thanks!

ipdb debugger, step out of cycle

Is there a command to step out of cycles (say, for or while) while debugging on ipdb without having to use breakpoints out of them?
I use the until command to step out of list comprehensions, but don't know how could I do a similar thing, if possible, of entire loop blocks.
I believe this is the intent of the until command. It's like a next except that when a jump occurs to a previous line number for the loop, it will continue until exiting the loop.
unt(il)
Continue execution until the line with a number greater than the current
one is reached or until the current frame returns
In general, to "step out" of the current function, use return.
r(eturn)
Continue execution until the current function returns.
You can use j <line number> (jump) to go to another line.
for example, j 28 to go to line 28.
This could sound obvious: jump makes you jump.
This means that you don't execute the lines you jump: you should use this to skip code that you don’t want to run.
You probably need tbreak (Temporary breakpoint, which is removed automatically when it is first hit. The arguments are the same as break) as I did when I found this page.
If you are willing to use another debugger, trepan, has more ways you can step. It is more gdb-like. So you can give a count of how many times you want to step. Or you can give a line number in a continue debugger command which in essence sets a temporary breakpoint at the line and then issues "continue". Other things that change stepping are "set different". See also the even suffixes you can put on step.
Note that like ipdb, there is syntax highlighting of the source text.

PyCharm: debugging line by line?

I am using PyCharm (community version) for my Python IDE. I want the program to debug in a line-by-line fashion. So I don't want to set every line as a break point... Is there a way I could do this?
As #Cyber mentioned, the debugging hotkeys will let you step through line by line, step down into function calls, etc., once you've hit a breakpoint and stopped somewhere.
If you really want to step through each line, you could set a breakpoint somewhere at the very beginning of your code. If you're using a main() function in your code, e.g.:
def main():
....
if __name__ == '__main__':
main() # Breakpoint here, 'Step Inside' to go to next line
then you could set the breakpoint at the call to main(). (If you're not, you might want to try this approach.)
One other thing I'd point out is PyCharm's easy-to-overlook feature of conditional breakpoints. If you right-click on the breakpoint symbol in the gutter area of the editor, you can type in a condition, like n > 10; the breakpoint only triggers when that line is executed and the condition is met. When you're trying to debug code issues within a recursive function, say, this can simplify things a lot.
I know the last part isn't really what you were asking for, but as your codebase gets bigger, going through each line can get really time consuming. You'll probably want to focus more on things like unit testing and logging with larger projects.
To run in debug mode press the 'bug' button (or Shift + F9).
Step over - F8
Step into - F7
Step out - Shift+F8.
Step to next breakpoint (or end) - F9
The pdb module only needs 2 lines of code in your program to be able to step through line by line.
import pdb # Insert this as the first line of your program
pdb.set_trace() # Insert this once in your program to step through it
# code you want to step into
This youtube video explains everything in 6 mins.
As mentioned above you can use the hotkeys, alternatively, you can use the debugger UI:
The blue arrows on the top allow you to step over, step into, or step out.

Is it possible to remove a break point set with ipdb.set_trace()?

I used ipdb.set_trace() somewhere in my Python code. Is it possible to ignore this break point using a IPDB command?
clear tells me that it cleared all break points, but IPDB stops again when it stumbles upon the line with ipdb.set_trace().
disable 1 tells me: No breakpoint numbered 1
ignore 1 says: Breakpoint index '1' is not valid
To clarify: Of course I could simply remove the break point from my source code. But this would require to quit the debugger and to start it again. Often it needs a lot of work to get somewhere and restarting the debugger makes life more difficult. Also if there is a huge loop and you want inspect objects in the loop, the easiest is to place a break point in the loop directly after the object. How could I then skip the loop (and all thousands of calls set_trace()) and step through the code after the loop using next?
Well, you CAN take advantage of the fact that anything in Python is an object. While in the debugger, you can do something like this:
def f(): pass
ipdb.set_trace = f
set_trace will still be called, but it won't do anything.
Of course, it's somewhat permanent, but you can just do
reload ipdb
and you'll get the original behaviour back.
(why would you do this? when you accidentally put a breakpoint in an often-called function that is usually called under a try/except. Once you realize you're stopping 1000 times in this function, you try to ctrl-c, but that gets caught by the try/except and you're back in ipdb again. So, if you're in low-level code, make sure your set_traces have some context:
if myvar in ['some', 'sentinel', 'values']:
ipdb.set_trace()
etc.
After learning from Corley
ipdb.set_trace = lambda: None
Works for me.
Based on Corley and GLaDOS answers, you can use this trick to set_trace for several loops without overwriting the ipdb.set_trace()
import ipdb
dbg1 = ipdb.set_trace # BREAKPOINT
for i in range(10):
my_var2 = 10 / 3
dbg1() # BREAKPOINT
dbg1 = lambda: None
print(my_var2)
dbg2 = ipdb.set_trace # BREAKPOINT
for i in range(10):
my_var2 = 20 / 3
dbg2() # BREAKPOINT
dbg2 = lambda: None
print(my_var2)
Works for me like a charm.
Running the program should also tell you exactly where you've set your idb.set_trace() when it's being hit (otherwise, try the where or bt commands). You can then remove that line from the file, and restart the program.
Otherwise, you might find this useful, if you feel more experimental.

Categories

Resources