This notebook contains an excerpt from the Python Programming and Numerical Methods - A Guide for Engineers and Scientists, the content is also available at Berkeley Python Numerical Methods.

The copyright of the book belongs to Elsevier. We also have this interactive book online for a better learning experience. The code is released under the MIT license. If you find this content useful, please consider supporting the work on Elsevier or Amazon!

< CHAPTER 10. Errors, Good Programming Practices, and Debugging | Contents | 10.2 Avoiding Errors >

Error Types

We have noted errors before but have not yet talked about them in detail. There are three basic types of errors that programmers need to be concerned about: Syntax errors, runtime errors, and Logical errors. Syntaxis the set of rules that govern a language. In written and spoken language, rules can be bent or even broken to accommodate the speaker or writer. However, in a programming language the rules are rigid. A syntax error occurs when the programmer writes an instruction using incorrect syntax and Python can not understand what you are saying. For example, 1 = x is not legal in the Python programming language because numbers cannot be assigned as variables. If the programmer tries to execute one of these instructions or any other syntactically incorrect statement, Python will return an error to the programmer and point out the line where the error occurred. Note: the complained location is where the syntax error is detected by the parser, sometimes, the place causing the error may be far away from the pointed out line.

EXAMPLE: Syntax error examples.

1 = x
  File "<ipython-input-1-7a7b257d8e3d>", line 1
    1 = x
SyntaxError: can't assign to literal
  File "<ipython-input-2-800df0a5e99c>", line 1
SyntaxError: invalid syntax
if True
  File "<ipython-input-3-025e9fce1ee3>", line 1
    if True
SyntaxError: invalid syntax

The last line of the error message shows what happened - SyntaxError, and the lines before indicate where the error happens in the context of the code. Overall, syntax errors are usually easily detectable, easily found, and easily fixed.

Even if all the syntax are correct in your code, it may still cause an error during execute the code. Errors that occur during execution are called exceptions or runtime errors. Exceptions are more difficult to find and are only detectable when a program is run. Note: exceptions are not fatal. We will learn later how to handle them in Python. If we do not handle them, Python will terminate the program. Let us see some examples below.

ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-4-9e1622b385b6> in <module>
----> 1 1/0

ZeroDivisionError: division by zero
x = [2]
x + 2
TypeError                                 Traceback (most recent call last)
<ipython-input-5-29a14b9fefb9> in <module>
      1 x = [2]
----> 2 x + 2

TypeError: can only concatenate list (not "int") to list
NameError                                 Traceback (most recent call last)
<ipython-input-6-bca0e2660b9f> in <module>
----> 1 print(a)

NameError: name 'a' is not defined

AS shown in the examples above, there are different types of built-in exceptions: ZeroDivisionError, TypeError, and NameError. You can find a complete list of built-in exceptions in the Python documentation. Of course, you can define your own exception types, but we will not deal with this herein; if you are interested in how to define customized exceptions, check out here.

Most of the exceptions are easy to locate because Python will stop running and tell you where the problem is. After programming a function, seasoned programmers will usually run the function several times, allowing the function to “throw” any errors so that they can fix them. But no exception does not mean the function works correctly.

One of the most difficult kinds of errors to find is called a logic error. A logic error does not throw an error and the program will run smoothly, but is an error because the output you get is not the solution you expect. For example, consider the following erroneous implementation of the factorial function.

def my_bad_factorial(n):
    out = 0
    for i in range(1, n+1):
        out = out*i
    return out

This function will not produce a runtime error for any input that is valid for a correctly implemented factorial function; however, if you try using my_bad_factorial, you will find that the answer is always 0 because out is initialized to 0 instead of 1. Therefore, the line out = 0 is a logic error. It does not produce a runtime error by Python, but it leads to an incorrect computation of factorial.

Although the logic errors seem unlikely to occur–or at least as easy to find as other kinds of errors–when programs become longer and more complicated, these types of errors are very easy to generate and notoriously difficult to find. When logic errors occur, you have no choice but to meticulously comb through each line of your code until you find the problem. For these cases, it is important to know exactly how Python will respond to every command you give and not make any assumptions. You can also use Python’s debugger, which will be described in the last section of this chapter.

< CHAPTER 10. Errors, Good Programming Practices, and Debugging | Contents | 10.2 Avoiding Errors >