Reading an error message
Beginners see a red block of text and feel caught out. Experienced programmers see the same block and feel relieved, because Python has just told them exactly what is wrong and where.
Nothing separates those two reactions except knowing how to read it.
Read the last line first
An error message is not a paragraph. It has a shape, and the useful part is at the bottom:
scores = [10, 8, 9]
print(scores[7])
The last line says:
IndexError: list index out of range
Two halves, both worth having:
IndexError— the kind of problem. There are perhaps eight you will meet all year.list index out of range— the detail. You asked a three-item list for item seven.
Everything above that last line is the traceback: the trail of which line was running. When your programs are short it tells you little. When they are long it is how you find the guilty line. Either way, read from the bottom up.
The ones you will actually meet
NameError — Python does not know that word
message = "Hello"
print(mesage)
NameError: name 'mesage' is not defined. Almost always a typo, or a variable
used before it was created. To Python, mesage is simply a word it has never
been taught.
Run it and you will see modern Python go one better: Did you mean: 'message'? It compares the unknown word against the names it does know and offers the closest. When it makes that suggestion it is nearly always right — but it is a guess, not knowledge, so read it rather than accepting it blindly.
TypeError — right idea, wrong kind of thing
age = "13"
print(age + 1)
TypeError: can only concatenate str (not "int") to str. "13" is text and 1
is a number, and Python refuses to guess whether you wanted 14 or "131".
The fix is to say which you meant:
age = "13"
print(int(age) + 1)
14
This is the strings-versus-numbers distinction from lesson three, showing up where it actually costs you something.
KeyError — no such key
marks = {"maths": 82}
print(marks["art"])
KeyError: 'art'. The dictionary has no art. Either a typo in the key, or a
key you assumed would be there — which is exactly what .get() is for.
ValueError — right type, impossible value
print(int("hello"))
ValueError: invalid literal for int() with base 10: 'hello'. You handed int()
a string, which is fine, but that particular string is not a number. The
difference from TypeError is worth holding on to: wrong kind of thing versus
wrong value of the right kind.
ZeroDivisionError — exactly what it says
scores = []
print(sum(scores) / len(scores))
ZeroDivisionError: division by zero. This one is nearly always an empty list
somewhere, and it is the reason careful code checks if len(scores) > 0 before
dividing.
Syntax errors are different
Every error so far happened while the program was running. A SyntaxError
means Python could not understand your writing well enough to start at all:
if 5 > 3
print("yes")
SyntaxError: expected ':'. Nothing ran — not even a line before the mistake.
That is the tell: if a print at the very top of your program did not appear,
you have a syntax error, not a logic problem.
Its close relative:
if 5 > 3:
print("yes")
IndentationError: expected an indented block. The if promised a block and
none arrived. Indentation is not decoration in Python; it is how the language
knows what belongs to what.
A worked example
def average(scores):
return sum(scores) / len(scores)
marks = {"maths": 82, "science": 91}
print(average(marks["art"]))
Read the bottom line: KeyError: 'art'.
Now note what it is not. It is not a problem with average, even though
average is where you were doing the interesting work. Python never got that
far — it failed while working out what to hand over. The traceback above the
last line confirms it, pointing at the print line rather than anything inside
the function.
That is the habit worth building: the last line tells you what, the lines above tell you where, and the two together usually make the fix obvious.
When the message does not help
Sometimes there is no error at all and the answer is simply wrong — like the
introduce(13, "Ayesha", ...) example two lessons ago. Python cannot catch
that, because nothing is broken as far as the rules go.
For those, the oldest tool still works best: print the thing just before it goes wrong.
def total(scores):
running = 0
for score in scores:
print("adding", score, "to", running)
running += score
return running
print(total([1, 2, 3]))
adding 1 to 0 adding 2 to 1 adding 3 to 3 6
Four extra characters, and the loop stops being a black box. Delete the line when you are done.
Errors are not a sign you are bad at this. Every program you will ever write will produce them, including the ones written by people who have done it for twenty years. The only difference is how quickly they get read.
Prefer learning with a teacher?
WasiLearn Academy runs small-group classes covering this material, online and in Karachi.
See the classes