Exception Handling
An out-of-range access on a Vec throws an exception that the programmer is able to catch.
Try it: try / except / else / finally
How an exception jumps out of a try block to the first matching except clause, when else runs, and why finally always runs.
How it works
- Statements in try run until one raises an exception; the rest of try is skipped.
- Python checks the except clauses in order and runs the first one whose type matches.
- If nothing was raised, the else block runs instead.
- finally runs in every case.
Default run (9 steps): Call safe_divide('4'). … Return 25.0. Output was: Worked: 25.0 / Done.
Simplified: One fixed function; int() and / are modelled exactly (including how Python prints floats), but nothing is executed as Python.
Loading the simulation…
A Missing Position in a List of Readings
Suppose a program keeps a list of readings in a Vec and asks for the element at a position that does not exist. The position might have come from user input, or a calculation might have produced a number one too large. Either way, the program has asked for something outside the bounds of the container. This article explains what the language does at that moment and how a programmer can take control of the outcome instead of leaving it to chance.
What do you think happens?
A Vec holds five readings. The program asks for the element at a position that is not among them. Does the program simply get a value back, or does something else happen?
Reveal answer
An exception is thrown. For a Vec, an out-of-range access throws an exception, and the programmer is able to catch that exception.
The container detects the bad position and announces the failure by throwing. Whether the program then continues or ends depends on code the programmer wrote in advance.
Keep one practical question in mind while reading: when a failure like this happens, is the program's future decided by the failure itself, or by code the programmer wrote beforehand?
What an Out-of-Range Access Does
A Vec holds a fixed run of elements, and each access asks for one of them by position. A position inside the Vec refers to a real element. A position outside the Vec refers to nothing. When the program asks for a position outside the Vec, the access is out of range.
In the diagram, the first five positions name real elements, while position 5 names nothing. Asking for position 5 is the kind of request that the source describes as an out-of-range access. For a Vec, that request throws an exception.
An exception is a signal that a failure has happened. The Vec does not decide what the program does next. It only reports that the access could not be completed. The source makes the point that this event is something the programmer is able to catch, which means the program can be written so that the failure is handled rather than ignored or left to end the run without comment.
Throwing Versus Catching
The source separates two actions that work together. Throwing announces that a failure has occurred. Catching is what the program does in response. The two are distinct: the container throws, but catching is an active choice made by the programmer.
Control Flow When an Exception Is Caught or Missed
The difference between the two outcomes is the central lesson here. The same exception, thrown at the same moment, either lets the program continue or ends it. The only thing that differs is whether a handler was written to catch it.
In the caught case, the statements after the handler's region are reached through the handler, and the program carries on. In the uncaught case, the statements that would have followed the failed access are skipped, and the program ends. The source describes that ending as a well-defined termination rather than an undefined one.
How an Exception Travels Up the Call Stack
Catching an exception does not always happen at the exact spot where the bad access occurred. A failure can start deep inside a chain of function calls. The exception then moves outward through the callers until some code that has a handler receives it. The diagram below traces one such chain in an illustrative program.
If a function on this chain has a handler, the exception stops there. If none does, the exception reaches main(). That is the place where the try-block technique described next becomes important, because it means a missed exception still arrives at a place where something has been prepared to handle it.
Wrapping main() in a Try-Block
Catching every exception at the exact point where it might occur is not always practical. The source describes a broader safety measure: write main() with a try-block as its body. The whole program then runs inside that try-block, so exceptions that were not caught closer to their origin still arrive at a handler.
A try-block used as the body of main() provides default exception handlers. These handlers print an error message to cerr. The result is that a missed exception is reported in a known place, on a known stream, rather than appearing as a surprise after the program has already stopped.
Tracing One Failure from Start to Finish
A Readings Program With and Without a Handler
A program stores five readings in a Vec. It later asks for the element at position 5, which does not exist. Trace what happens in the case where a handler wraps the access, and in the case where no handler exists.
- 1Step 1: Access the Vec
The program asks for position 5. Position 5 is outside the Vec, so the access is out of range.
- 2Step 2: Throw
The Vec throws an exception. Throwing announces that the failure occurred.
- 3Step 3: Look for a handler
With a handler present, the exception is caught and the handler runs. Without one, nothing catches it in this region, and the exception moves outward.
- 4Step 4: Continue or end
With a handler, the program continues from the handler. Without one and with no outer handler, the program terminates in a well-defined way.
The same thrown exception produces two different futures. The only difference is whether the programmer wrote a handler in advance.
| Stage | Caught case | Uncaught case |
|---|---|---|
| Out-of-range access | Occurs | Occurs |
| Exception | Thrown | Thrown |
| Handler | Runs | None in this region |
| Program | Continues from handler | Terminates in a well-defined way |
Trace of one failed Vec access under two conditions
Mistakes Beginners Make With Exceptions
Common mistake Assuming an uncaught exception produces chaos
Why it failsThe source describes an uncaught exception as leading to a defined end of the program, not an undefined one.
Do this insteadTreat an uncaught exception as a predictable termination, and decide deliberately whether that ending is acceptable.
Common mistake Believing the container catches the exception for you
Why it failsThe Vec throws, but catching is an active choice by the programmer.
Do this insteadWrite a handler where the program needs to recover, or rely on an outer handler on purpose.
Common mistake Expecting a try-block around main() to make the program always succeed
Why it failsThe try-block only ensures a missed exception is reported in a known place on a known stream.
Do this insteadUse the try-block to make failures visible, and still write closer handlers where recovery matters.
Common mistake Forgetting that a caught exception means execution continues from the handler, not from the failed access
Checking Your Understanding of Propagation
A function fetch_reading accesses position 7 of a Vec that holds five elements. The function has no handler. Its caller read_readings also has no handler. main() has a try-block as its body. Where does the exception stop, and what does the user see reported?
Hints
- Follow the chain of callers outward from the failed access.
- Ask which code has a handler, and which code only has the default reporting from the try-block around
main().
Key Takeaways
- An out-of-range access on a Vec throws an exception, and the programmer is able to catch that exception.
- Throwing announces a failure; catching lets the program continue from the handler. An uncaught exception ends the program in a well-defined way.
- The same thrown exception either lets the program continue or ends it, depending entirely on whether a handler was written to catch it.
- A try-block used as the body of
main()provides default handlers that print an error message to cerr, which minimizes surprises from uncaught exceptions without guaranteeing success.