livepython.net
CHAPTER 17Handling Errors (Exceptions)
17.1  EXCEPTIONS

Python Exceptions: Read Errors and Know Their Types

What Is an Exception in Python?

An exception is an error that happens while your program is running. Python stops at the line that fails and tells you what went wrong. The lines before it have already run; the lines after it never run.

PYTHONedit me
print("Start")
price = 300
people = 0
print(price / people)
print("End")
OUTPUT
Start
ZeroDivisionError: division by zero

Start was printed, because line 1 ran fine. Then line 4 tried to divide by zero, and the program stopped. End never appeared.

Think of it like a smoke alarm in a kitchen. Everything is fine until the moment something burns. Then the alarm goes off, cooking stops, and the alarm tells you what the problem is.

Two kinds of errors

You met both kinds in chapter 1. Now they get proper names:

KindWhen Python finds itExamples
Syntax errorbefore the first line runsa missing colon, a missing bracket
Exceptionwhile the program runs, at the line that failsdividing by zero, int("abc")

A syntax error means Python can't even read your code, so nothing runs, not even line 1:

PYTHONedit me
print("Start")
print("Hi"
OUTPUT
SyntaxError: '(' was never closed

The rules

  • An exception stops the program at the line that fails.
  • Everything before that line has already happened.
  • Every exception has a type, like ZeroDivisionError, and a message, like division by zero.

Common beginner doubt: "Does an exception mean my code is wrong?" Not always. Sometimes it's a bug, like a typo in a name. But sometimes the code is fine and the input is bad: the user types abc where you asked for a number. You can't stop users from typing that. What you can do is handle the exception, so your program reacts calmly instead of crashing. That's what this chapter is about.

An exception is an error at run time: Python stops at that line, and the lines after it never run.

your turnPick the right idea

How many lines does this program print before it stops?

print("one") print("two") print(5 / 0) print("three")
Think about it, then pick one.
your turnPick the right idea

Which one is a syntax error, not an exception?

Think about it, then pick one.

How to Read a Python Traceback

A traceback is the error report Python prints when an exception stops a program. It looks scary, but you read it from the bottom up: the last line says what went wrong, and the lines above say where.

Here is the full report for the division example, as Python prints it on a computer:

Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(price / people)
          ~~~~~~^~~~~~~~
ZeroDivisionError: division by zero

Think of it like a doctor's note. The last line is the diagnosis: what's wrong. The lines above are the details: where it hurts.

The parts

PartWhat it tells you
Traceback (most recent call last):an error report starts here
File "main.py", line 3the line where it happened
print(price / people)the code on that line; the ^ marks point at the part that failed
ZeroDivisionErrorthe error type: what kind of problem
division by zerothe message: the details

In this course, the output box shows only the most useful line, the last one:

PYTHONedit me
price = 300
people = 0
print(price / people)
OUTPUT
ZeroDivisionError: division by zero

How to read any error

  1. Read the type. It tells you the kind of problem (you'll learn the common ones next).
  2. Read the message. It often names the exact value that caused it.
  3. Go to the line. Look at the code there.
  4. Ask where the values came from. The bug may be on an earlier line, like people = 0 here.

That's the debugging habit from chapter 3: every error is a clue, not a punishment.

Common beginner doubt: "The traceback is long. Do I need all of it?" Usually not. Start at the last line. When your code calls a function, the traceback lists each call on its way down, but the last line still tells you what went wrong.

Read a traceback from the bottom: the type and message say what went wrong, the line number says where.

your turnSpot the bug

Which line breaks?

One line stops this program. Tap it.
your turnPick the right idea

In this error, which part is the error type?

ValueError: invalid literal for int() with base 10: 'abc'
Think about it, then pick one.

NameError, TypeError and ValueError

Python has many error types, but a few show up again and again. Each name tells you the kind of problem, so knowing them saves a lot of time. Here are the first three.

Think of them like warning lights in a car: one for fuel, one for the engine, one for the doors. Each light points you to a different place to look.

TypeWhat it meansTypical cause
NameErrorPython doesn't know this namea typo, or a variable used before it's made
TypeErrorthe right kind of value is missingjoining text and a number with +
ValueErrorthe kind is right, but the value is wrongint("abc")

NameError: a name Python doesn't know

PYTHONedit me
name = "Sunny"
print(nmae)
OUTPUT
NameError: name 'nmae' is not defined

Look closely at the message: nmae, not name. A NameError is almost always a typo, or a variable used before the line that makes it.

TypeError: the wrong kind of value

PYTHONedit me
age = 12
print("Rocky is " + age)
OUTPUT
TypeError: can only concatenate str (not "int") to str

You saw this one in chapter 5. + can join two strings or add two numbers, but not one of each. The fix: an f-string, or str(age).

ValueError: the right kind, the wrong value

PYTHONedit me
marks = int("ninety")
OUTPUT
ValueError: invalid literal for int() with base 10: 'ninety'

int() does take a string, so the type is fine. But this particular string isn't a number. You met this in chapter 7, when a user typed a word instead of digits.

Telling TypeError and ValueError apart

  • TypeError: "I can't do this with that kind of thing." A number where text should be, or the other way round.
  • ValueError: "I can do this with that kind of thing, but not with this one." Text is fine for int(), but not the text "ninety".

NameError: a name Python doesn't know. TypeError: the wrong kind of value. ValueError: the right kind, but a bad value.

your turnFix the code

Fix the code so it prints: Lucky is 9

It should print: Lucky is 9

age = 9
print("Lucky is " + age)
This code does not work yet. Fix it, then press Run.
your turnPick the right idea

Which error does this line give?

total = float("twelve")
Think about it, then pick one.

IndexError, KeyError and ZeroDivisionError

Three more error types complete the list you'll meet most. Two of them come from collections (lists and dictionaries), and one from maths.

Think of a row of lockers. Ask for locker 10 in a row of 3, and there's no such locker. Ask for a locker by a name that isn't on any door, and nobody can find it. Those are the next two errors.

TypeWhat it meansTypical cause
IndexErrorthat position doesn't existitems[5] in a list of 3 items
KeyErrorthat key isn't in the dictionaryprices["cake"] when there is no cake
ZeroDivisionErroryou divided by zero/, // or % with 0 on the right

IndexError: no item at that position

PYTHONedit me
friends = ["Sunny", "Rocky", "Lucky"]
print(friends[3])
OUTPUT
IndexError: list index out of range

Three items have the indexes 0, 1 and 2 (chapter 9). Index 3 is one past the end. Strings give the same error: "Hi"[5].

KeyError: no such key

PYTHONedit me
prices = {"tea": 20, "coffee": 30}
print(prices["cake"])
OUTPUT
KeyError: 'cake'

The message is the missing key itself. You learned two ways to avoid it in chapter 13: check with in first, or use get().

ZeroDivisionError: dividing by zero

PYTHONedit me
total = 90
count = 0
print(total // count)
OUTPUT
ZeroDivisionError: division by zero

Maths has no answer for "divide by zero", so Python stops. It often happens with an average of an empty list, or when a user types 0.

Avoid: trusting that a key is there

PYTHONedit me
stock = {"pen": 4}
print(stock["book"])
OUTPUT
KeyError: 'book'

Good: check first

PYTHONedit me
stock = {"pen": 4}
if "book" in stock:
    print(stock["book"])
else:
    print("No books")
OUTPUT
No books

Common beginner doubt: "Should I always check with if first?" For lists and dictionaries, if and get() work well. But some problems, like text that isn't a number, are hard to check with if. That's where try and except shine, in the next topic.

IndexError: no such position. KeyError: no such key. ZeroDivisionError: you divided by 0.

your turnFill the gap

Avoid the KeyError

prices = {"tea": 20, "coffee": 30} item = "tea" if item ? prices: print(prices[item]) else: print("Not on the menu")

It should print: 20

Which piece makes this code work?
your turnPredict the output

What will this print?

prices = {"tea": 20} print(prices.get("cake", 0))
Your turn! What will this code show on the screen?

Practice: Exceptions

Solve these to lock in what you learned in this topic. Each one runs in your browser.

  1. 150.Fix a TypeError in a Birthday MessageEasySolve
  2. 151.Fix a KeyError in a Price LookupMediumSolve