Building better programs in Python (Part 3)
Error messages for syntax errors
If we're going to benefit from error messages, we need to understand what they are saying. Here are some examples that were presented earlier as well as the error messages that were generated.
Example 1
Running the code
print(31 23)
gives the error
Traceback (most recent call last): File "<string>", line 1 print(31 23) ^ SyntaxError: invalid syntax
This syntax error indicated where the error was, but didn't specify what the error was.
Example 2
Running the code
def f(x, y)
z = x + y
gives the error
Traceback (most recent call last): File "<string>", line 1 def f(x, y) ^ SyntaxError: invalid syntax
In this example, we had a missing colon and, again, no details were given.
Example 3
Running the code
def f(x, y):
z = x + y
return z
gives the error
Traceback (most recent call last): File "<string>", line 3 SyntaxError: 'return' outside function
Here, the return statement was indented incorrectly and the error message made it clear that it had to do with the return statement.
Decoding error messages
Let's look at a few more examples. We consider a code that has an incomplete line, so we can anticipate a syntax error. Running the code
print("string
gives the error
Traceback (most recent call last): File "<string>", line 1 print("string ^ SyntaxError: EOL while scanning string literal
The message refers to a “string literal”, which means a value that is a string, and EOL, which means end of line. That is, the computer was looking for a matching quotation mark but instead reached the end of the line. Let's supply the quotation mark and see what happens: running the code
print("string"
gives the error
Traceback (most recent call last): File "<string>", line 1 print("string" ^ SyntaxError: unexpected EOF while parsing
The computer ran into EOF, that is, the end of the file, while parsing, that is, while trying to figure out the syntax of what had been written. In other words, it was trying to match the opening parenthesis but the program ended.
Here's a summary of what we learned, including the abbreviation EOL, and a meaning of the first error message:
-
EOL means End Of Line
SyntaxError: EOL while scanning string literal means “I was reading a string but reached the end of the line before it ended.” -
EOF means End Of File
SyntaxError: unexpected EOF while parsing means “I was expecting to read more to make sense of what I'd read so far, but then I reached the end.”
Common syntax errors
- Missing colon
- Unmatched quotes, parentheses, or brackets
- Use of
=
instead of==
- Inconsistent or missing indentation
- Using a reserved keyword as an identifier
Since not all error messages are particularly descriptive or understandable, it is worth keeping in mind common errors, such as my speciality, leaving out colons, or unmatched quotation marks or parentheses, as we just saw in the example, or square or curly brackets, which we'll use later. Use of =
instead of ==
is a mistake that I make a lot. Inconsistent or missing indentation is one that can be hard to detect if tabs and blank spaces are interpreted differently. Another tricky one is accidentally using a reserved keyword as an identifier. You can look on the help page to find a list of such words.
Caution
Where the error is detected may not be where the error occurred.
If you have trouble finding the error at the spot indicated by the output message, keep in mind that, although the error was detected at that point, it might have occurred earlier.
Semantics errors
Syntax errors are relatively easy to handle because of the error messages that are generated. For semantics errors, you need to use tests to check that what is produced is what you wanted.
Example 1
Consider the code
print(2 * input("Enter a number: "))
In this example the user input was printed twice as it was interpreted as a string, not a number.
Example 2
Consider the code
def is_odd_string(word):
if len(word) % 2 == 1:
return True
print(is_odd_string("ab"))
Here None
is printed, since the function did not return a value when the string was even.
Example 3
Consider the code
def is_vowel(char):
is_a = char == "a" or "A"
is_e = char == "e" or "E"
is_i = char == "i" or "I"
is_o = char == "o" or "O"
is_u = char == "u" or "U"
return is_a or is_e or is_i or is_o or is_u
print(is_vowel("b"))
Here, the result is the string A, which was interpreted as a Boolean due to our mistaken use of or
.
Error messages for runtime errors
Let's now look at runtime errors that we generated earlier.
TypeError
Even if you don't understand the details, the fact that it is a “TypeError” gives you a big clue: there is a mismatch between the type of data you have provided and the type that is required. For example, running the code
print("high" + 5)
gives the error
Traceback (most recent call last): File "<string>", line 1, in <module> TypeError: Can't convert 'int' object to str implicitly
In this case, after a string and a plus sign, it was a string, not an integer, that should have been provided.
ValueError
In this example, we are using int
on a string that was not a string form of an integer: running the code
print(int("dog"))
gives the error
Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: invalid literal for int() with base 10: 'dog'
Here we have a ValueError. There again is the term “literal”. We're being told that it is the wrong kind of value.
ZeroDivisionError
In this example, we are trying to divide by zero, which is made quite clear by the error message: running the code
def is_multiple(number, factor):
return number % factor == 0
print(is_multiple(10, 0))
gives the error
Traceback (most recent call last): File "<string>", line 4, in <module> File "<string>", line 2, in is_multiple ZeroDivisionError: integer division or modulo by zero
IndexError
Running the code
def starts_with_a(word):
return word[0] == "a"
print(starts_with_a(""))
gives the error
Traceback (most recent call last): File "<string>", line 4, in <module> File "<string>", line 2, in starts_with_a IndexError: string index out of range
The error here was caused by the fact that we were using the index 0 on the empty string, which is one kind of index error. More generally, this kind of error occurs when the index is for a position that is not in the string.