Raising and catching custom exceptions
The else block in exception handling runs only when the try block succeeds without raising an exception.
The Success Path Matters
Exception handling has two broad outcomes: the risky operation either succeeds or raises an exception. A try-except-else structure makes those outcomes explicit. The try block contains the operation being attempted, except blocks respond to particular exception types, and the optional else block contains code for the success path. The key rule is that else runs only when the try block finishes without raising an exception.
The Execution Route
Python evaluates the try block first. If the operation succeeds, Python skips the except blocks and enters else. If the operation raises an exception, Python immediately looks for a matching except block. After the matching handler runs, the else block is skipped. This means there is no route in which an exception is handled and then else also runs.
The decision is made by what happens inside try. A successful completion selects else; an exception selects a matching except block.
Why Else Is Separate
You could place success-path statements directly after the risky operation inside try, but then those statements are also being monitored by the exception handlers. If one of them raises an exception, the except blocks may handle it even though the original risky operation succeeded. Placing success-only logic in else separates the operation being monitored from the code that should run after successful completion.
Keep error-handling logic in except blocks and success-path logic in else. This makes the intended route clear and avoids accidentally treating an exception from later success code as though it came from the original risky operation.
Separate Responses for Separate Events
A try block can have multiple except blocks. Each one names a specific exception type and can provide a different response. Python checks these handlers from top to bottom and executes the first one whose exception type matches. The remaining except blocks are skipped.
Tracing User Input
Three possible input outcomes
A program attempts to read text from a user. Its structure has a try block for the input operation, one except block for EOFError, a second except block for KeyboardInterrupt, and an else block that displays the entered text. Which part runs in each situation?
Ordinary text: The user enters text. The input operation completes without raising an exception, so both except blocks are skipped and else runs.
End-of-file signal: The user sends an end-of-file signal, such as Ctrl+D on Unix/Linux or Ctrl+Z on Windows. EOFError is raised, the EOFError handler runs, and else is skipped.
Keyboard interrupt: The user presses Ctrl+C. KeyboardInterrupt is raised, the KeyboardInterrupt handler runs, and else is skipped.
Normal text selects else. An end-of-file signal selects the EOFError handler. Ctrl+C selects the KeyboardInterrupt handler.
| Situation | Exception raised | Block that runs | Does else run? |
|---|---|---|---|
| User enters text | None | else | Yes |
| User sends an end-of-file signal | EOFError | EOFError except block | No |
| User presses Ctrl+C | KeyboardInterrupt | KeyboardInterrupt except block | No |
Execution outcomes for the input-handling pattern
The else block does not mean that no input event occurred. It means the try block completed normally. Ordinary text therefore reaches else, while either interruption reaches its matching except block.
Mistakes Beginners Make
Assuming else always runs after try.
When an exception is raised, Python moves to the matching except block and skips else.
Fix:
Ask first whether try completed without an exception. Only that outcome reaches else.Treating all failures as one indistinguishable case.
Different exception types can represent different events and can be handled by separate except blocks.
Fix:
Use a specific except block for each exception type that needs a different response.Putting success-path logic in try without considering its monitoring scope.
That code is also monitored by the except blocks. An exception from it may be handled as though it came from the input operation.
Fix:
Place success-only logic in else when separating it from the risky operation improves clarity and correctness.Expecting more than one matching except block to run.
Python executes the first matching except block and skips the remaining except blocks.
Fix:
Read except blocks from top to bottom and stop at the first match.
Practice the Prediction
What do you think happens?
A try block attempts to get user input. The user presses Ctrl+C. Which block executes next?
Reveal answer
Answer: The KeyboardInterrupt handler
Ctrl+C raises KeyboardInterrupt. Python checks the except blocks in order, selects the first matching KeyboardInterrupt handler, and skips else and the remaining handlers.
For each situation, predict the next block before checking the explanation: the user enters ordinary text; the user sends an end-of-file signal; the try operation completes normally but the learner expects both an except block and else to run.
Hints
- Start by identifying whether the try operation raises an exception.
- If an exception is raised, identify its type and find the matching handler.
- Remember that else is reserved for normal completion.
Key Takeaways
- The try block runs first and contains the operation being monitored for exceptions.
- Python selects the first except block whose exception type matches the raised exception.
- The else block runs only when try completes without raising an exception.
- EOFError and KeyboardInterrupt can have separate handlers with tailored responses.
- Keeping success logic in else separates it from the code whose exceptions should be handled.
Key Takeaways
- The else block represents successful completion of try, not a block that always follows it.
- An exception sends control to the first matching except block and skips else.
- Multiple specific except blocks allow different responses for EOFError and KeyboardInterrupt.
- Predicting control flow starts by classifying the event: normal completion, EOFError, or KeyboardInterrupt.
- Separating success logic into else keeps the exception-monitoring boundary clear.