Big picture
Even a correct program can fail at run time: a user types letters instead of a number, a file is missing, or a value is divided by zero. Such run-time errors are exceptions. If an exception is not handled, Python stops the program and prints an error message (a traceback).
Exception handling lets a program catch these errors and respond sensibly: show a helpful message, ask again, or clean up. In Python this is done with try, except, else and finally. Board questions ask you to name the exception a statement raises, write handling code, and predict the output when an exception occurs.
Learning goals
Distinguish syntax errors from exceptions.
Name common built-in exceptions and the situations that raise them.
Use
tryandexcept, including multipleexceptblocks.Use
elseandfinallycorrectly, and trace the flow of control.Raise exceptions with
raiseand check conditions withassert.
Core ideas
1. Syntax errors and exceptions
Basis | Syntax error | Exception |
|---|---|---|
When it is detected | Before the program runs (while parsing) | While the program is running |
Cause | Code breaks Python's grammar rules | A valid statement can't be carried out |
Example | Missing colon: |
|
Can it be handled with try–except? | No, the program can't start | Yes |
SyntaxError and IndentationError are reported before execution; all others in this chapter occur at run time.
2. Common built-in exceptions
Exception | Raised when | Example |
|---|---|---|
| Dividing or taking a remainder by zero |
|
| A function gets an argument of the right type but an inappropriate value |
|
| An operation is applied to an object of the wrong type |
|
| A name that hasn't been defined is used |
|
| A sequence index is out of range |
|
| A dictionary key doesn't exist |
|
| A file to be opened doesn't exist |
|
| A module or name can't be imported |
|
|
| |
| The user presses Ctrl+C during execution | |
| A calculation result is too large to represent |
|
| Incorrect indentation |
3. try and except
Code that might raise an exception goes in a try block. If an exception occurs, Python skips the rest of the try block and jumps to the matching except block.
for v in ['5', 'x']:
try:
n = int(v)
print(10 / n)
except ValueError:
print('VE')
except ZeroDivisionError:
print('ZE')
# output:
# 2.0
# VEMultiple except blocks handle different exceptions differently. Python checks them in order and runs only the first matching block.
except (ValueError, TypeError):handles several exceptions in one block.except ValueError as e:stores the exception object, so its message can be printed: for[1, 2][5]the message islist index out of range.A bare
except:catches every exception; place it last, and use it with care because it can hide bugs.
4. else and finally
The `else` block runs only if no exception occurred in the
tryblock.The `finally` block always runs, whether or not an exception occurred, and even if the
tryblock contains areturn. It is used for clean-up, such as closing files.
def div(a, b):
try:
r = a / b
except ZeroDivisionError:
print('Cannot divide by zero', end='; ')
return None
else:
print('Result', r, end='; ')
return r
finally:
print('Done')
div(10, 2) # Result 5.0; Done
div(1, 0) # Cannot divide by zero; DoneOrder of blocks: try → except (one or more) → else (optional) → finally (optional). else can't appear without at least one except.
finally even runs before a return:
def t():
try:
return 1
finally:
print('F', end=' ')
print(t()) # F 15. Flow of control when an exception occurs
Python executes the
tryblock statement by statement.If an exception occurs, the remaining statements of the
tryblock are skipped.Python looks for a matching
exceptblock. If found, it runs; if not, the exception passes up to the caller, and if no handler exists anywhere, the program stops with a traceback.If no exception occurs, the
elseblock runs.The
finallyblock runs in every case.
6. Raising exceptions: raise and assert
`raise` lets a program signal an error deliberately, for example when an input is invalid:
def age_check(a):
if a < 0:
raise ValueError('Age cannot be negative')
return a
try:
age_check(-3)
except ValueError as e:
print(e) # Age cannot be negative`assert` tests a condition and raises an AssertionError (with an optional message) if it is False. It is mainly used while debugging to check assumptions:
try:
assert 5 > 10, 'five is not greater'
except AssertionError as e:
print('AE', e) # AE five is not greater7. Why handle exceptions?
The program doesn't crash; it can show user-friendly messages and recover.
Error-handling code is separated from normal code, so programs are clearer.
Resources such as files and database connections can be released in
finally.
A reliable routine for exception questions
Identify which statement fails first and the exact exception it raises.
Skip the rest of the
tryblock after that statement.Find the first
exceptthat matches; if none matches, the exception propagates.Run
elseonly if nothing failed; always runfinally.Write the outputs in order, paying attention to
end=in print statements.
Connections that matter
File handling uses
try–exceptforFileNotFoundErrorandfinally(orwith) to close files.Python–SQL connectivity handles database errors and closes connections.
Functions can raise exceptions that are handled by the caller.
Common mistakes
Expecting `try`–`except` to catch a syntax error.
Putting a general `except` before specific ones, so the specific blocks never run.
Thinking `else` runs after an exception. It runs only when there was no exception.
Thinking `finally` is skipped when there is a `return`. It still runs.
Mixing up `ValueError` and `TypeError`:
int('abc')is ValueError;'2' + 2is TypeError.
Revision checklist
I can distinguish syntax errors from exceptions.
I can name the exception raised by common statements.
I can write
try–exceptwith multiple handlers.I can use
elseandfinallyand trace their order.I can use
raiseandassert.