Skip to content
Lesson 10 of 12

Step 1 of 7 · Reading · ~4 min

Learn

Error Handling

Try and Except

You have already met the crashes: int("abc") is a ValueError, a missing dict key is a KeyError, a bad list index is an IndexError. This lesson is how to keep the program running through them, and how to read input when you do not know how many lines are coming.

What runs, and when

python

except runs only if the try body raised a matching error, and the rest of the body is abandoned at the line that raised. else runs only if the body finished without raising. finally runs every time, including when the body exits through return, break or continue:

python

The finally line prints before the caller prints the returned value. Put code in else rather than at the end of try when an error in that code should not be caught by your except.

Which errors an except matches

An except matches the named class and every subclass of it. KeyError and IndexError share the parent LookupError, ZeroDivisionError sits under ArithmeticError, and nearly everything sits under Exception. A tuple names several classes at once.

python

as e binds the exception object, and type(e).__name__ is its class name. str(e) gives the message (division by zero, or 'z' for a KeyError), but that wording belongs to Python and changes between versions, so print the class name when the output must be stable. e is deleted when the except block ends: using it afterwards raises NameError.

Handlers are tried top to bottom and the first match wins. Put the narrow class first:

python

Broad handlers hide bugs

python

The bare except swallowed the NameError caused by the typo, and it also catches Ctrl+C. With except ValueError the same program stops and names the typo. Catch the classes you expect, and keep except Exception for a place that records the error.

Python style is EAFP, "easier to ask forgiveness than permission": attempt the operation and handle the failure, as opposed to checking first like in or .get(). It wins when the check is as hard as the job: "-12".isdigit() is False, yet int("-12") works.

Reading until the input ends

input() raises EOFError when no lines are left, which is how a program reads input of unknown length. A last line without a trailing newline is still returned normally.

python

For the lines 20.5, abc, a blank, 22.5 and 23 this prints 3 readings, 1 rejected.

Common mistakes

  • A class missing from the tuple. If IndexError is not listed, a line with a missing argument crashes the program with a traceback instead of printing an error line.
  • Printing str(e). You get error division by zero where error ZeroDivisionError was expected.
  • Counting in the wrong clause. Adding to the success count inside try before the value is checked, or counting blank lines, makes the totals too high.
  • Treating an unknown value as success. A command the program does not recognise raises nothing, so it reaches else looking like a success. Check the value there.

Your exercise

Build a command evaluator that reads until end of input and reports each line. The starter handles reading and blank lines; you supply the try structure and the counting. The likeliest slip is forgetting that a missing argument raises IndexError.

Up nextRaising ExceptionsError Handling

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…