Thursday, 14 September 2017

Errors and Debugging

There may be flawless programmers out there, who type exactly what the computer understands and get exactly the results they require, first time round, no problems or mistakes.
I am not one of those. I get things wrong, sometimes with worrying frequency. My mistakes fall into two broad categories; syntax errors where the computer and Python interpreter don't understand or like what I've typed in and refuse to run the program, and logical errors where the Python interpreter can read and follow my instructions but produce results that I don't want or expect.

Syntax errors

These are generally simple omissions or misspelling. Typical syntax errors that I make include: leaving the colon off the end of a for loop line, misspelling a variable name so the interpreter thinks a new variable is being introduced, starting a statement with an opening parenthesis '(' and then leaving the closing parenthesis ')' off.  Almost unique to Python are errors associated with indentation - most languages don't consider indentation important (they typically use curly braces { } instead), but for Python interpreter, indentation shows how parts of the program are nested in each other. Other error messages will emerge if:
  • you try to import a module Python does not have installed
  • you try to use a function Python does not recognise
  • you get confused between = for assignment and == for comparison (a regular one for me!)
  • type errors are when the interpreter is expecting a number and it gets a string, or it gets a string but was expecting a number. Data types are a whole subject unto themselves, but it is fair to say Python can be quite particular about what data types are used where. 
Syntax errors are fairly easy to detect - the computer will tell you in no uncertain terms that there is something wrong with this program. These error messages can be simple and straightforward, or occasionally indirect and cryptic. The good news is that with practice you get to know what each error message means without needing to study and analyse it too much. We have encountered one of these error messages when trying to convert a string with a decimal point into an integer:
>>> foo = "34.325"
>>> int(foo)
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    int(foo)
ValueError: invalid literal for int() with base 10: '34.325'
A lot of syntax errors are picked up by Python when you first tell it to run (F5 in IDLE) but sometimes they crop up while it is running - run-time errors.

Logical Errors

These are not picked up by the interpreter - as far as Python is concerned, the program can run fine. But what you get is not what you want. In the previous post I had the script:
#!/usr/bin/python3
print ("Savings Calculator")
deposit = 100.00
interest = 0.030
year = 2017
savingyears = 20
print(year, deposit)
for i in range(savingyears):
    deposit = deposit + (deposit * interest)
    year += 1
    print (year, deposit)
That was the finished script, but the first version had an error. Instead of
    deposit = deposit + (deposit * interest)
I had
   deposit = deposit * interest
This gave the unintended results of
>>>
===== RESTART: C:/Users/pc/Documents/Programming/test02_errorexample.py =====
Savings Calculator
2017 100.0
2018 3.0
2019 0.09
2020 0.0026999999999999997
2021 8.099999999999999e-05
2022 2.4299999999999996e-06
2023 7.289999999999998e-08
2024 2.1869999999999996e-09
2025 6.560999999999998e-11
2026 1.968299999999999e-12
2027 5.904899999999998e-14
2028 1.7714699999999992e-15
2029 5.3144099999999976e-17
2030 1.5943229999999992e-18
2031 4.7829689999999975e-20
2032 1.4348906999999993e-21
2033 4.3046720999999973e-23
2034 1.2914016299999992e-24
2035 3.8742048899999977e-26
2036 1.1622614669999993e-27
2037 3.486784400999998e-29
>>>
 I really hope my bank account does not have that sort of interest rate. For those not mathematically minded, the part where it says e-y it is shorthand for the first number divided by 10 y times. Again, the computer does not recognise anything wrong - it has no problem doing what it is told. The problem is I have told it to do the wrong thing.

Debugging

There is no magic bullet here that can instantly remove bugs before you know what's going on. Instead I have a basic process for debugging
  • I look at the output, including any error messages and any line numbers mentioned
  • I look at my script and see what might have gone wrong
  • I make whatever corrections I think are needed
  • I run the program again
  • If the program runs as intended, then it has been successfully debugged. 
  • If not, and it is the same or similar problem that shows up, I go back to the start of this list
  • Sometimes I solve one bug, run the program and find that there are several different bugs - I now have to deal with the next one in line. 
I have occasionally been hindered by a rather elusive bug. Here print statements at particular points in the program can show onscreen what certain variables are at these points. If the printed results are what I want and expect then I can assume that the program is functioning as intended up to that point, and the bug is further on in the code.

No comments:

Post a Comment