← Teacher guide

When things go wrong

Students catch errors with try and except so typed mistakes get a reply instead of a crash, compare it with checking first (isdigit), and catch two kinds of error in one program.

Deeper Python in the console · Errors and the adventure · about 45 minutes · Open the student lesson

Classroom resources

Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.

Students will be able to

Timing

Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 10 min

Before class

Read the unit primer first. try: runs its lines; if one causes the named error, Python jumps to except ThatError: and then carries on after it. Only the named error is caught: the bug task catches ValueError when the error is a KeyError, so the program still stops. int() accepts " 4 " and "-2" but not "3.5" or "three", so a caught error does not check whether a number is sensible (the first Investigate question). Avoid a bare except: that catches everything: it hides real mistakes.

Running the lesson

  1. Predict: trace it on the board. The line after int() never runs.
  2. Run: ask students to find every kind of answer that gets through (including -2).
  3. Investigate: compare with isdigit() from the console bridge. Both are fine; try is the usual Python way.
  4. Bug task: read the error's name in the message, then the except line.
  5. Make: two excepts after one try. Ask which one runs for 10 / 0 and for ten.

The hard part (on purpose)

Catching the error that actually happens. Ask them to read the error's name in the message and match it to the except, rather than catching everything.

When students get stuck

What you will seeA question to askThe fix
The program still stops with an error.Which error does the message name, and which does your except catch?Catch the error the message names (KeyError, not ValueError).
The loop never ends, even with a good answer.Where is break, and does it run when the answer is good?Put break inside try, after the line that might fail.
NameError on a variable after the loop.Was the variable given a value inside try before the loop ended?Only leave the loop (break) once the value has been set.

Answers to the checks

  1. Predict: What does it print?
    That is not a number. then Done. int("twelve") causes a ValueError, so Python skips the rest of try and runs the except lines. Then the program carries on after them.
  2. Which answers pass?: Which answer does int() accept, so the loop stops?
    -2
    int("-2") is the number -2, so nothing goes wrong and the loop stops, charging $-24. A caught error is not the same as a sensible answer: the program still has to check the number.
  3. Try or check first?: Compared with isdigit() in the console bridge, what does try let you do?
    Just try it, and handle the error if it happens
    isdigit() checks first; try does it and catches the error. Python programmers often say it is easier to ask forgiveness than permission.
  4. Spot the bug: This should say There is no such room, but it stops with KeyError: attic. Click the line that is wrong.
    line 4
    except ValueError only catches a ValueError. A missing key is a KeyError, so it should be except KeyError:.
  5. Where this leads: A game loads a saved file that has been deleted. What should a well-made program do?
    Catch the error, say the save is missing, and start a new game
    Files, networks and people all go wrong. Catching the error and carrying on sensibly is what makes a program feel solid.

Solutions

One possible solution for each task. Other correct programs are fine.

Modify › One to ten

prices = {"pie": 5, "drink": 3, "fruit": 2}
while True:
    item = input("What would you like? ").strip().lower()
    try:
        price = prices[item]
        break
    except KeyError:
        print("We have: " + ", ".join(prices))
while True:
    text = input("How many? ")
    try:
        count = int(text)
        if count >= 1 and count <= 10:
            break
        print("Choose 1 to 10.")
    except ValueError:
        print("Please type a whole number.")
print("That will be $" + str(price * count) + ".")

Modify › Quit

prices = {"pie": 5, "drink": 3, "fruit": 2}
price = 0
while True:
    item = input("What would you like? ").strip().lower()
    if item == "quit":
        break
    try:
        price = prices[item]
        break
    except KeyError:
        print("We have: " + ", ".join(prices))
if item != "quit":
    while True:
        text = input("How many? ")
        try:
            count = int(text)
            break
        except ValueError:
            print("Please type a whole number.")
    print("That will be $" + str(price * count) + ".")
else:
    print("Goodbye!")

Make a safe calculator

while True:
    try:
        a = int(input("First number: "))
        b = int(input("Divide it by: "))
        print("Answer: " + str(a / b))
        break
    except ValueError:
        print("Please type whole numbers.")
    except ZeroDivisionError:
        print("You can't divide by zero. Try again.")

Stretch and support

Stretch: Make a function ask_number(question) that keeps asking until it gets a whole number, and use it twice.

Support: Give students the try and the first except of the calculator, and ask them to add the second except.

Exit ticket

try: n = int("3.5") except ValueError: n = 0. What is n?

0: int("3.5") causes a ValueError, so the except line runs.

What each step is for

Where it leads

Next lesson is the text adventure. Later, saving and loading a game uses the same idea for a missing file (FileNotFoundError).