Talk to your Teddy (Debugging)
June 25, 2011 5 Comments
One of the irritating things about writing programs is that, often, when you type your program in perfectly, it still doesn’t work. You’ve got bugs! (Apparently, one of the first errors in the operation of a computer occurred because a moth got stuck in amongst the componentry. Its removal thus started the act of debugging computer programs.)
The good news is that, in every tutorial I’ve done on this blog I have had at least one, and often many, bugs in the programs I’ve written – even the ones which are only 2 or 3 lines long!!!! Getting things wrong is a natural part of writing programs. We need to know how to get things right after they are wrong. So in this tutorial I wanted to talk about bugs and debugging and things to look for when trying to get your programs running.
The two main causes of bugs we’re going to look at are syntax errors and logical errors.
Syntax errors
A syntax error means that you’ve said something to the computer which doesn’t make grammatical sense. Thus, if you were to say to your sibling, “Yesterday I the car,” they’d have absolutely no idea what you were talking about. That’s because this sentence doesn’t fit with English rules of grammar (it lacks a verb). Similarly, Python programs have their own “grammar”. If you deviate from that grammar the Python interpreter is unable to work out what you mean.
Often a syntax error is caused by a single typo somewhere in the code. Here are some examples:
>>> def aFunction File "<stdin>", line 1 def aFunction ^ SyntaxError: invalid syntax
Can you see here that the interpreter is trying to tell you where the problem is? The caret ^ shows where Python thinks that there is a problem. The interpreter is not always right, but this is a good place to start.
>>> def aFunction() File "<stdin>", line 1 def aFunction() ^ SyntaxError: invalid syntax
First, the interpreter expects a function to have a list of parameters, so is looking for a pair of parentheses -> (). Then, it also expects to see a colon -> : to mark where the function’s code starts.
>>> def aFunction():
...
File "<stdin>", line 2
^
IndentationError: expected an indented block
Here, the interpreter sees that you’ve tried to define a function, but hasn’t found any code for the function. Code for a function is indented, hence, if it’s not there, the interpreter thinks that there’s a problem with the indentation.
>>> def aFunction(): ... print "this is a function" ...
Note that you need to press return on a blank line to finish the function’s definition if you are in the interpreter. This is not the case if you are using a text file for your program. Leaving out a colon or having the wrong indentation are perhaps two of the most frequent syntax errors. As a refresher, Python uses indentation to mark off code blocks. This means that all the code which is to be executed at the same code level must be indented to the same indent level. There is no “right” level of indentation, as long as the indentation is consistent. So these are both ok:
>>> def aFunction(): ... print "First line of code" ... print "second line of code" ... >>> def bFunction(): ... print "first line of code" ... print "second line of code" ... >>> aFunction() First line of code second line of code >>> bFunction() first line of code second line of code
However, the function below won’t work because the level of indents (ie the number of spaces before the text starts) is different for each line within the same code block. A code block is (always? <- not sure) marked off by a colon : in the previous line.
>>> def cFunction(): ... print "first line of code" ... print "second line of code" File "<stdin>", line 3 print "second line of code" ^ IndentationError: unexpected indent
Where you have a function you need to pass it the right number of arguments:
>>> range() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: range expected at least 1 arguments, got 0 >>> range(3) [0, 1, 2]
The range() function is interesting in that it can take between 1 and 3 arguments (the second and third arguments are optional). However if you pass no arguments, or more than 3, then the interpreter will complain to you.
Logical Errors
Logical errors are usually harder to diagnose. When you write the program, because you have used the right syntax, the Python interpreter doesn’t tell you that there’s an error. Nevertheless, when you run it, you get the wrong answer or the program crashes half way through. Logical errors often happen with loops, for example, where you forget that the range() function starts at zero, or you have got some other offset incorrect. They can also happen where you use a function, but don’t understand what it does, or what output it is supposed to produce.
When faced by a logical error, the usual way to debug is to break down the program into different components and to inspect each in turn. When you’re more advanced, you can put logging messages into the code and Python will log the progress of the program to a separate log file. For the time being however, the easiest thing to do is to put a print statement in. You put a number of print statements in and sooner or later one of them will print the wrong thing. Then you know that the error is before that print statement, but after the previous one.
Others
Usually if you make a mistake it will show up as one of these two errors. However, sometimes you’ve just made a typing mistake but haven’t realised it – like typing * instead of + somewhere.
Lastly and Most Importantly – Talk to your Teddy
I’ve left the most important bit to last. When you have a debugging problem that you really just can’t solve, get your teddy bear (I’m serious, get your bear), bring it to the monitor and explain (in words, out loud) to your teddy what the problem is and why it isn’t working.
This is a sure-fire, clinically proven way to solve whatever debugging problem you have. As I mentioned earlier, I’m absolutely serious about sitting your teddy down beside you and talking (with your voice, not in your head) to it. Now, it doesn’t absolutely have to be a teddy. It could be a Lego figure, or an action figure, a parent or a sibling (if they’re willing) or even a balloon with a face and ears drawn on in pen.
The important thing is that you explain aloud in words what the problem is, because that helps you identify it for yourself.