Reading errors

Part of the free LogicWiz Python course, Module 7: Errors and debugging. The examples and practice run in the app.

Aarav's bill program worked yesterday. Today it printed a wall of red text and stopped. He scrolled straight past it, but the answer was sitting on the last line: ZeroDivisionError: division by zero.

You'll learn to

  • Tell syntax, runtime and logical errors apart
  • Read a traceback from the bottom up and find the line to fix
  • Recognise the common exceptions: NameError, TypeError, ValueError, ZeroDivisionError, IndexError, KeyError

Learn

Three kinds of errors

Every bug you will ever meet is one of three kinds:

  • Syntax error: Python can't even read the code (a missing : or bracket). Nothing runs, not even line 1.
  • Runtime error (exception): the code is valid, but one line can't be done (dividing by zero, a missing key). The program runs until that line, then stops with a traceback.
  • Logical error: the program runs and finishes, but the answer is wrong. No red text, no message. These are the hardest, because Python thinks everything is fine.

A syntax error: nothing runs

print("Bill starts")
total = 50 + 20
print("Total:", total

Run it. Even the first print does not run: Python checks the whole file before running any of it. Add the missing ) and run again.

A runtime error: runs until the bad line

print("Bill starts")
plates = 0
total = 120
print("Per plate:", total / plates)
print("Done")

"Bill starts" prints, then line 4 fails. "Done" never prints. Change plates to 4 and run again.

A logical error: no red text, wrong answer

marks = [80, 90, 70]
average = sum(marks) / 2     # we meant len(marks)
print("Average:", average)

It prints 120.0, an average higher than every mark. Python did exactly what we wrote; we wrote the wrong thing. Only you can catch this, by checking the answer makes sense.

Reading a traceback, bottom up

A traceback is Python's report of where it was when things went wrong. Read it from the bottom:

  1. Last line: the error type and message, e.g. KeyError: 'dosa'. This tells you what went wrong.
  2. The line above it: the file, line number and the actual code that failed. This tells you where.
  3. Lines above that: the chain of function calls that led there. "most recent call last" means the deepest call is at the bottom.

The line that failed is not always the line with the bug. Walk up the chain and ask: where did the bad value come from?

A traceback through two functions

def per_head(total, people):
    return total / people

def split_bill(total, friends):
    share = per_head(total, len(friends))
    return round(share, 2)

print(split_bill(240, ["Riya", "Kabir"]))
print(split_bill(240, []))

The first call prints 120.0. The traceback for the second shows three steps: line 9 called split_bill, line 5 called per_head, line 2 divided by zero. The real problem is the empty list passed on line 9, not the division on line 2.

The exceptions you will meet most

ErrorTypical cause
NameErrorA typo in a name, or using a name before giving it a value: totl
TypeErrorMixing types that don't go together: "5" + 3, len(5)
ValueErrorRight type, bad value: int("two")
ZeroDivisionErrorx / 0, x // 0 or x % 0
IndexErrorPosition past the end: marks[3] when there are 3 marks
KeyErrorA dict key that is not there: menu["pizza"]
AttributeErrorA method the object doesn't have: "chai".append("s")
IndentationErrorWrong indentation; it is a kind of SyntaxError

CBSE asks you to classify an error (syntax, runtime or logical) and to find the errors, rewrite the code and underline each correction. Remember: IndentationError is a syntax error, ZeroDivisionError is a runtime error, and a logical error gives no message at all.

For a missing bracket, Python often points at the line after the real mistake, because that is where it finally got confused. If the reported line looks fine, look at the line just above it.

In one line

Syntax errors stop the file before it runs, runtime errors stop at the bad line, logical errors give wrong answers silently; read a traceback from the bottom up.