Sometimes when other quick attempts at debugging fail, you need a way to take a deeper look into your script. Most integrated development environments (IDEs) like Pyscripter include some debugging tools that allow you to step through your script line-by-line to attempt to find an error. These tools allow you to keep an eye on the value of all variables in your script to see how they react to each line of code. The Debug toolbar can be a good way to catch logical errors where an offending line of code is preventing your script from returning the correct outcome. The Debug toolbar can also help you find which line of code is causing a crash.
The best way to explain the aspects of debugging is to work through an example. This time, we'll look at some code that tries to calculate the factorial of an integer (the integer is hard-coded to 5 in this case). In mathematics, a factorial is the product of an integer and all positive integers below it. Thus, 5! (or "5 factorial") should be 5 * 4 * 3 * 2 * 1 = 120.
The code below attempts to calculate a factorial through a loop that increments the multiplier by 1 until it reaches the original integer. This is a valid approach since 1 * 2 * 3 * 4 * 5 would also yield 120.
# This script calculates the factorial of a given # integer, which is the product of the integer and # all positive integers below it. number = 5 multiplier = 1 while multiplier < number: number *= multiplier multiplier += 1 print (number)
Even if you can spot the error, follow along with the steps below to get a feel for the debugging process and the PyScripter Debug toolbar.
Open PyScripter and copy the above code into a new script.
Step through the loop until "multiplier" reaches a value of 10. It should be obvious at this point that the loop has not exited at the desired point. Our intent was for it to quit when "number" reached 120.
Can you spot the error now? The fact that the loop has failed to exit should draw your attention to the loop condition. The loop will only exit when "multiplier" is greater than or equal to "number." That is obviously never going to happen as "number" keeps getting bigger and bigger as it is multiplied each time through the loop.
In this example, the code contained a logical error. It re-used the variable for which we wanted to find the factorial (5) as a variable in the loop condition, without considering that the number would be repeatedly increased within the loop. Changing the loop condition to the following would cause the script to work:
while multiplier < 5:
Even better than hard-coding the value 5 in this line would be to initialize a variable early and set it equal to the number whose factorial we want to find. The number could then get multiplied independent of the loop condition variable.
Click the Stop button in the Debug toolbar to end the debugging session. We're now going to step through a corrected version of the factorial script, but you may notice that the Variable window still displays a list of the variables and their values from the point at which you stopped executing. That's not necessarily a problem, but it is good to keep in mind.
Open a new script, paste in the code below, and save the script as debugger_walkthrough2.py
# This script calculates the factorial of a given # integer, which is the product of the integer and # all positive integers below it. number = 5 loopStop = number multiplier = 1 while multiplier < loopStop: number *= multiplier multiplier += 1 print (number)
In the above example, you used the Debug toolbar to find a logical error that had caused an endless loop in your code. Debugging tools are often your best resource for hunting down subtle errors in your code.
You can and should practice using the Debug toolbar in the script-writing assignments that you receive in this course. You may save a lot of time this way. As a teaching assistant in a university programming lab years ago, the author of this course saw many students wait a long time to get one-on-one help, when a simple walk through their code using the debugger would have revealed the problem.
Read Zandbergen 7.1 - 7.5 (11.1 - 11.5 if you have the old ArcMap version of the book) to get his tips for debugging. Then read 7.11 (11.1 in the old version) and dog-ear the section on debugging as a checklist for you to review any time you hit a problem in your code during the next few weeks. The text doesn't focus solely on PyScripter's debugging tools, but you should be able to follow along and compare the tools you're reading about to what you encountered in PyScripter during the short exercise above. It will also be good for you to see how this important aspect of script development is handled in other IDEs.