Concepts / Error Handling with Try-Except Blocks

Error Handling with Try-Except Blocks

Error handling is not always about responding after an error occurs.

  • Programming
Interactive lab

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

  1. Statements in try run until one raises an exception; the rest of try is skipped.
  2. Python checks the except clauses in order and runs the first one whose type matches.
  3. If nothing was raised, the else block runs instead.
  4. 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.

Educational simulation

Loading the simulation…

Before the Error Happens

Error handling is not always about responding after an error occurs. Python can sometimes avoid an error entirely by stopping a logical expression before it reaches a risky operation. This behavior is called short-circuit evaluation, and it is the basis of the guardian pattern.

Key point

The central question is not only whether an operation could fail. It is also whether Python will evaluate that operation at all.

Left-to-Right Evaluation

Definition

Short-circuit evaluation stops evaluating a logical expression once its result is already determined.

Python evaluates the parts of a logical expression from left to right. In an and expression, the whole expression must be False if the first part is False, so Python does not need to inspect the remaining part. In an or expression, the whole expression must be True if the first part is True, so Python stops there instead.

First partEvaluate left sideFalseand stopsFalseand resultTrueor stopsTrueor resultSecond partEvaluate only when neededandFalseorTrueTrueFalse
How does Python evaluate each condition from left to right, and where does it stop once the result is already determined?
OperatorFirst partWhat happens
andFalsePython stops and the whole expression is False
orTruePython stops and the whole expression is True

The first value that determines the result prevents later parts from being evaluated.

Tracing a Risky Division

Consider the expression x >= 2 and (x/y) > 2. The first part, x >= 2, acts as a condition that Python checks before the division. If x is less than 2, the first part is False. Because this is an and expression, Python already knows that the complete result must be False and never evaluates (x/y) > 2.

Worked example

Three evaluations of one expression

Trace x >= 2 and (x/y) > 2 for three different value combinations.

  1. 1
    Case one

    When x >= 2 is True and y is suitable for the division, Python evaluates both parts because it must inspect the second part to determine the final result.

  2. 2
    Case two

    When x >= 2 is False, Python stops immediately. The division is never attempted, even if y is zero.

  3. 3
    Case three

    When x >= 2 is True and y is zero, Python proceeds to the second part. The division by zero then causes a ZeroDivisionError.

Result

The division is reached only when the first part of the and expression is True.

What do you think happens?

Suppose x is less than 2 and y is zero. In x >= 2 and (x/y) > 2, will Python attempt the division?

  • Yes, because the division appears in the expression

  • No, because the first part is False

  • Only after evaluating both parts

Reveal answer
Answer:

No, because the first part is False.

The and expression is already known to be False when its first part is False. Python short-circuits before evaluating the division, so the ZeroDivisionError does not occur in this case.

The Guardian Pattern

Definition

The guardian pattern places a safe guard condition before a risky operation so that short-circuit evaluation prevents the risky operation from running when its required condition is not met.

In x >= 2 and (x/y) > 2, x >= 2 is the guard. The guard does not make division mathematically safe in every situation. Instead, it controls whether Python reaches the division at all. When the guard is False, the and expression stops before the risky operation.

x >= 2Guard conditionFalseStop evaluationx/yRisky operation(x/y) > 2Evaluate second partFalseTruethen
How does checking a value before performing division prevent Python from reaching a ZeroDivisionError?
Best practice

Always place the guard condition first. If the risky operation appears before the guard, Python may evaluate the risky operation before it has a chance to use the guard.

Choosing the Guard

The operator and the guard must work together. With and, the guard must become False to prevent the second part from running. With or, the guard must become True to prevent the second part from running. Reversing this relationship can cause the risky operation to be evaluated instead of skipped.

In the real world

The guardian pattern can also protect a list access. The guard len(my_list) > 0 ensures that my_list[0] is accessed only when the list is not empty. If the list is empty, the guard is False and the potentially invalid access is never evaluated, preventing an IndexError.

Try-Except Context

The broader topic is error handling with try-except blocks, but the supplied material concentrates on preventing errors before a risky operation runs. The guardian pattern can avoid some runtime errors without adding extra try-except blocks. The key mechanism covered here is short-circuit evaluation: a guard prevents Python from reaching the operation that could fail.

try blockAttempt operationOperationSucceeds or raises errorContinueNo errorexcept blockHandle matching errorrunsuccesserror
What happens to control flow when an operation raises an error, and how does execution move from the try block to the matching except block?

Practice the Decision

MEDIUM

For each expression, identify whether the second part is evaluated when the first part has the stated value. Then explain whether the guardian prevents the risky operation.

Hints
  • For and, a first part that is False stops evaluation.
  • For or, a first part that is True stops evaluation.
  • Check the operator before deciding whether the guard prevents the second part.
  • In x >= 2 and (x/y) > 2, what happens when x >= 2 is False?
  • In a and b, when is b skipped?
  • In a or b, when is b skipped?
  • Why must a guard be placed before the risky operation?
  • How can len(my_list) > 0 protect access to my_list[0]?

Common Evaluation Mistakes

  • Common mistake

    Assuming every part of a logical expression is always evaluated.

    What it looks like
    x >= 2 and (x/y) > 2
    Why it fails

    If x >= 2 is False, Python stops before evaluating the division.

    Do this instead

    Trace the expression from left to right and check whether the first part already determines the result.

  • Common mistake

    Remembering the and rule but applying it to or.

    What it looks like

    Treating a first True value in an or expression as if evaluation must continue.

    Why it fails

    A first True value already determines an or expression to be True.

    Do this instead

    Remember: and stops on False; or stops on True.

  • Common mistake

    Putting the risky operation before the guard.

    What it looks like

    Checking safety only after attempting a division or list access.

    Why it fails

    The risky operation may execute before the guard can prevent it.

    Do this instead

    Place the safe guard condition first.

  • Common mistake

    Believing a guard makes every later operation safe.

    What it looks like

    Using a guard that is unrelated to the possible error.

    Why it fails

    A guard prevents evaluation only when its truth value causes the logical expression to short-circuit.

    Do this instead

    Choose a guard that directly establishes the condition needed before the risky operation.

Key Takeaways

  • Python evaluates logical expressions from left to right.
  • An and expression stops when its first part is False.
  • An or expression stops when its first part is True.
  • The guardian pattern places a safe condition before a risky operation.
  • A correctly placed guard can prevent errors such as ZeroDivisionError and IndexError by stopping the risky operation from being evaluated.

Related concepts

More concepts starting with E