Any good programmer, especially ButchDean, will tell you that you have to know how to debug your code. Without the ability to utilize a debugger, you could end up spending hours, days, even weeks trying to find a very subtle flaw in your logic. For those of you who are new to programming, you may be wondering what exaclty a debugger does. Different debuggers have different features, but there are a few features that are common to most of them. Usually, you'll be able to stop your code at a given point (a breakpoint) and then inspect the variables available to you at that given spot in your code. At this point you will be able to step forward 1 line at a time and watch how your variables change. When you come across a function call, you'll have the option to examine what happens inside that function (step into), or just continue to the next line of code that you're currently inspecting (step over). At any point, you'll be able to tell the program to continue at normal speed, and stop if it hits another breakpoint.
To continue this discussion, let's use a trivial example. Look at the following code:
import random #find out which of the primes between 2 and 100 are in a given value #then return them in the provided list def primeFactorizer(seed = None, primeList = ): if seed == None: seed = random.randint(2,100) primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] for prime in primes: if seed % prime == 0: primeList.append(prime) print("Primes of "+str(seed)+": "+str(primeList))
The code is funky and breaks quite a few good programming practices; DO NOT use this as a template for any of your future projects. The point is that the code should randomly generate a value, and then list which of the first 25 primes are in that value. Keeping the values between 2 and 100 assures us that it will contain at least 1 of the first 25 primes. However, when I run it, I get some unexpected output:
>>> x = primeFactorizer()
Primes of 13: 
>>> y = primeFactorizer()
Primes of 80: [13, 2, 5]
x looks good, but y looks a little funny. What's with the 13? Like any programmer, you might be tempted to use print statements, but in the future you might hit errors you can't catch by just printing. Instead, let's restart IDLE. In the interactive shell, go to Debug in the menu and then choose Debugger. A debug control window should open.
Before you continue, take a moment to examine the window. You'll notice 4 checkboxes, I tend to use Stack, Locals, and Globals. You'll also notice 5 buttons. All of them are shaded, but once code is actually running through the debugger they'll all activate.
- Go tells the program to continue until it hits another breakpoint.
- Step tells it to step forward by 1 line. If there's a function, step will step into the function, allowing you to examine how it works. This can be kinda fun to play with when you're using a module you imported, like random for example.
- Over works like step, but will not step into functions, it steps over them instead.
- Out continues until the current function has been exited.
- Quit ends the program.
In your code window, you could set a breakpoint by right clicking on any line of code and choosing set breakpoint, but for this situation we don't really need one as the debugger will activate anytime we do something in the interactive shell. If we made a test script we would have more use for breakpoints.
>>> x = primeFactorizer(30)
At this point feel free to play around with the debugger. Examine what all the buttons do, except don't waste your time with 'Quit.' If you use quit, the code won't execute.
>>> y = primeFactorizer(2)
At this point you'll immediately see the problem. Your primeList still has the values from the previous run it it! This is due to a well-known 'gotcha' in Python involving default mutable variables.
Through this tutorial, we've managed to use IDLE's Debugger to troubleshoot a very trivial problem. In the next debugging tutorial, we'll further examine some debugging techniques and find out just what Debugging Control is really capable of.