PyCharm: debugging line by line? - python

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.

Related

DEBUG only one function (or module), RUN rest of the program in Pycharm?

I will try to explain my question on simple example program (my problem is much more complex because my program is much more complex).
Lets suppose i have a program that has 2 lines, making 2 functions:
data = long_one() #takes 2 hours in DEBUG mode, 15min in RUN mode
short_one(data) #i want to DEBUG this one
Lets also say that it is very difficult to prepare the data variable and the only way to obtain it is by running the function long_one().
Is there a way to RUN long_one() and DEBUG short_one() in Pycharm?
In other words is there a way to perform either:
DEBUG with specification that long_one() should be processed in RUN mode
or RUN with specification that short_one() should be debugged?
As Asagen has proposed:
attached debugger to python console.
started my script in RUN mode
while script was running I did Tools/Attach to Process and have chosen my process.
The debugger has started from the moment i did this and stopped on first breakpoint it encountered.
There was one inconvenience - I had to know when to start debugging (in which moment to attach debugger to process). I propose a workaround:
Add to code an infininte loop in place you want to start debugging (see below):
data = long_one() # takes 2 hours in DEBUG mode, 15min in RUN mode
infinite_loop = True
print "OK man, it is the time to start debugging!"
while infinite_loop:
time.sleep(0.2) # add breakpoint here
short_one(data) #i want to DEBUG this one
Add a breakpoint inside the while loop
While running process, when you see in console the printed text "OK man, it is the time to start debugging!", attach debugger to process.
Next when it stops in the infinite loop, evaluate code fragment infinite_loop = False, so you leave the loop
It is it, you are now in DEBUG mode after running whole code before,
If you want to get back to RUN mode, just stop debugger. It is possible to switch between RUN and DEBUG as many times and in any places you want
import sys
def do_the_thing_for_debug():
print('doing the debug version')
def do_the_thing():
print('doing the release version')
if __name__ == '__main__':
"""
Detecting if you're in the PyCharm debugger or not
WARNING: This is a hacky & there is probably a better
way of doing this by looking at other items in the
global() namespace or environment for things that
begin with PyCharm and stuff.
Also, this could break in future versions of PyCharm!
If you put a breakpoint HERE and look at the callstack you will
see the entry point is in 'pydevd.py'
In debug mode, it copies off sys.argv: "sys.original_argv = sys.argv[:]"
We abuse this knowledge to test for the PyCharm debugger.
"""
if hasattr(sys, 'original_argv'):
do_the_thing = do_the_thing_for_debug
do_the_thing()
Output from PyCharm when I "run" it
doing the release version
Output from PyCharm when I "debug" it
doing the debug version

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.

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.

Python File append error

This code works fine for me. Appends data at the end.
def writeFile(dataFile, nameFile):
fob = open(nameFile,'a+')
fob.write("%s\n"%dataFile)
fob.close()
But the problem is when I close the program and later run again I found that all the previous data were lost. Process is started to write from the start and there is no data in the file.
But during the run it perfectly add a line at the end of file.
I can't understand the problem. Please some one help.
NB: I am using Ubuntu-10.04 with python 2.6
There is nothing wrong with the code you posted here... I tend to agree with other the comments that this file is probably being overwritten elsewhere in your code.
The only suggestion I can think of to test this explicitly (if your use case can tolerate it) is to throw in an exit() statement at the end of the function and then open the file externally (aka in gedit) and see if the last change took.
Alternatively to the exit, you could run the program in the terminal and include a call to pdb at the end of this function which would interrupt the program without killing it:
import pdb; pdb.set_trace()
You will then have to hit c to continue the program each time this runs.
If that checks out, do a search for other places this file might be getting opened.

How do I skip a loop with pdb?

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.

Categories

Resources