How do I debug efficiently with Spyder in Python?

Question:

I like Python and I like Spyder but I find debugging with Spyder terrible!

  • Every time I put a break point, I need to press two buttons: first
    the debug and then the continue button (it pauses at first line
    automatically) which is annoying.
  • Moreover, rather than having the standard iPython console with auto completion etc I have a lousy ipdb>> console which is just garbage.
  • The worst thing is that this console freezes very frequently even if I write prints or simple evaluation to try to figure out what is the bug. This is much worse than MATLAB.
  • Last but not least, if I call a function from within the
    ipdb>> console, and put a breakpoint in it, it will not stop there.
    It seems like I have to put the breakpoint there before I start the
    debugging (Ctrl+F5).

Do you have a solution or maybe can you tell me how you debug Python scripts and functions?

I am using fresh install of Anaconda on a Windows 8.1 64bit.

Asked By: Hanan Shteingart

||

Answers:

(Spyder maintainer here) After our 4.2.0 version, released in November 2020, the debugging experience in Spyder is quite good. What we provide now is what people coming from Matlab would expect from a debugger, i.e. something that works like IPython and lets you inspect and plot variables at the current breakpoint or frame.

Now about your points:

  1. If there is a breakpoint present in the file you’re trying to debug, then Spyder enters in debug mode and continues until the first breakpoint is met. If it’s present in another file, then you still need to press first Debug and then Continue.

  2. IPdb is the IPython debugger console. In Spyder 4.2.0 or above it comes with code completion, syntax highlighting, history browsing of commands with the up/down arrows (separate from the IPython history), multi-line evaluation of code, and inline and interactive plots with Matplotlib.

  3. This is fixed now. Also, to avoid clashes between Python code and Pdb commands, if you have (for instance) a variable called n and write n in the prompt to see its value, we will show it instead of running the n Pdb command. To run that command instead, you have to prefix it with an exclamation mark, like this: !n

  4. This is fixed too. You can set breakpoints in IPdb and they will be taken into account in your current session.

Answered By: Carlos Cordoba

One minor extra regarding point 3:

It also seemed to me the debug console frequently froze, doing prints, evaluating, etc, but pressing the stop (Exit debug) button usually got it back to the bottom of the call stack and then I could go back up (‘u’) to the frame I was debugging in. Worth a try. This might be for a later version of Spyder (2.3.5.2)

Answered By: Paul

Here is how I debug in Spyder in order to avoid freezing the IDE. I do this if I alter the script while in debugging mode.

  1. I close out the current IPython (debugging) console [x]
  2. Open a new one [Menu bar-> Consoles-> Open an IPython Console]
  3. Enter debug mode again [blue play pause button].

Still a bit annoying, but it has the added benefit of clearing (resetting) variable list.

Answered By: oogieoogieful

The pdb debugger works just fine with regular python. So in Spyder, I just switch to the python console whenever I want to debug interactively.

import pdb

def yourfunction():
    # Interesting stuff done here
    pdb.set_trace() 

Nice intro to debugging with pdb https://pythonconquerstheuniverse.wordpress.com/category/python-debugger/

Answered By: LtGlahn

Debugging workflow

You have to understand that in fact you are using different integration of the Python debugger pdb and ipdb (which uses pdb and which can be accessed using the module ipdb). I hope this trivial example will help you with using it better.

Suppose you want to debug this code:

def Waiting_fun():                      #1 line number one
    for i in range(100):                #2
        pass                            #3
                                        #4 
def New_sum(lista, to_s = False):       #5
    result = 0                          #6
    print 1                             #7
    for i in lista:                     #8
        print "summed"                  #9   
        result +=i                      #10
    Waiting_fun()                       #11
    if to_s:                            #12
        result = str(result)
    return result
a = New_sum([1,4,5,7,8])
b = New_sum([1,4],1)
c = 456
d = New_sum([6,8,9],1)
final_result = a*b*c*d
Out: Type error

Quick first debugging using iPython %debug

%debug

The first thing I do is to call pdb from iPython using the magic command %debug, you can set it as a default mechanism using %pdb.

%debug
> /home/opdate/Desktop/test.py(23)<module>()
     19 a = New_sum([1,4,5,7,8])
     20 b = New_sum([1,4],1)
     21 c = 456
     22 d = New_sum([6,8,9],1)
---> 23 final_result = a*b*c*d

Once you have lunch pdb. You can find all command in the official docs or you can use the command h to display them. In this stage the only commands that I use are:

  • p : prints the variables that you specify
  • pp : pretty prints
  • args: if you are inside a function it prints the arguments
  • pp locals() : can be useful to print all the variables but most of
    the times it is a mess!
  • ! use it if you want to avoid conflicts with the commands listed in h
  • whatis variable_name: equivalent of type(variable_name)
  • u : Move the current frame one level up in the stack trace (to an older frame).
  • d : Move the current frame one level down in the stack trace (to a newer frame).
  • q : when you finish you can use q for quitting

In our case:

ipdb> pp a,b,c,d
(25, '5', 456, '23')

Or ipdb> !a,b,c,d (no space between esclamation mark and first value).
It’s clear that b and d are strings in case we can use:

ipdb> whatis b
<type 'str'>

Going deeper using break-points

70% of the times %debug points you to the solution. When you need more features like breakpoints is time to use Spyder. In this case, we want to understand why b is a string we put a breakpoint next to it (double-clicking next to the line number in the editor window). I find much better to use the standard Python console instead of the IPython console for debugging so select the console before starting debugging:
enter image description here

Then open the variable explorer if there are any variables delete them. I use Ctrl+F5 to start the debugging you can use the buttons on the top but I prefer to use their shortcuts shown below:

enter image description here

(Pdb) c # we go to the breakpoint 
(Pdb) s # we step into the function
(Pdb) args # we see what parameters are inserted
(Pdb) s # going step-by-step
(Pdb) ⏎ # series of Enters go line by line quicker
#Here I'll use  whatis command but in fact I just look to
# the type in variable explorer of spyder.
(Pdb) whatis result #check if result is still int
(Pdb) unt #or until -useful to exiting from loops see doc.
(Pdb) n # we  don't  enter to the Waiting_fun function
(Pdb) s # going step-by-step
(Pdb) whatis result #we find that there the int is converted
(Pdb) j 6 # for double checking we jump back to 6 were the result is assigned 
# We may be tempted to j(ump) to line 12 but doing so we would skip all the code
#for avoiding a series of `s`,`unt` and `n` we can use this solution:
(Pdb) tbreak 12 #set a new temporary breakpoint. Also `b` it's ok most of the time
(Pdb) c  # go to it 
(Pdb) j 6 # we jump to 6 the code we jump is NOT executed
(Pdb) whatis result# we find that if we jump 12-13 result is still int

Now we have located the error. We can also test a solution we repeat the step until 12 and we set to_s = False

(Pdb) to_s = False #!to_s = False to be on the safe side

It works. One important feature using the standard pdb in the Python console, is that you have auto competition and you can use the variable explorer instead of using whatis and pp:

enter image description here

Using the variable explorer you can also change the value of the variables which makes the things even quicker.

Conditional breakpoints

Another more clever way to locate the error is to use conditional breakpoint (Shift+F12) a great advantage of Spyder is going to debug and use list breakpoints. Conditional breakpoints are activated when the condition is True In our case, we want to locate where b becomes a string so the condition is: type(b) == str. I usually place a lot of conditional breakpoints and see which ones meet the condition. For doing so don’t use Shift+F12 but place normal breakpoints double-clicking next to the line and go to Debug->List breakpoints and copy and past the condition in the table to every breakpoint as shown in the figure below.

enter image description here

From here the commands to use are:

(Pdb) c  # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint
Answered By: G M

You can use debug shortcut keys like:
Step Over F10
Step Into F11
in tools>preferences>keyboard shortcuts

Answered By: Mahyar

No one has ever mentioned about these two before apparently:

Before Python, I was using VBA. Although it is a relatively old language that is not regularly updated, one thing I loved about VBA was the debugging function. The 2 debugging functions that are closest to VBA or which can also be termed as “visual debugging” I had come across are:

1-PyCharm Debugger

This 6 minutes video demonstrates PyCharm debugger.

2-PixieDebugger – The Visual Python Debugger for Jupyter Notebooks You’ve Always Wanted

Since many coders tend to use JupyterNotebook, this debugger would come in handy.
PixieDebugger is almost the same as PyCharm debugger. I will not go into detail in here.

But you can refer to this link

Answered By: mcagriardic
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.