LambdaLabTM
Computer Science · Class 12 · Exception Handling
Exceptionstry / except⏱️ 15 min read

try and except

An exception interrupts a program that was running. Left alone, Python prints a traceback and stops. Handling it means telling Python in advance what to do instead — and try and except are the two blocks that say it.

1Why bother? Two reasons, and both matter

Compare what a user sees. This is the unhandled version — a normal program, given a zero:

unhandled.py
print('--- Marks Calculator ---')

total = 250
subjects = 0

average = total / subjects

print('Average:', average)
print('--- Thank you ---')
Output
--- Marks Calculator ---
Traceback (most recent call last):
  File "unhandled.py", line 6, in <module>
    average = total / subjects
              ~~~~~~^~~~~~~~~~
ZeroDivisionError: division by zero

Six lines of red text, half of it about Python's own machinery, and the program is dead. The closing message never printed. To anyone who is not a programmer this looks like the computer broke.

handled.py
print('--- Marks Calculator ---')

total = 250
subjects = 0

try:
    average = total / subjects
    print('Average:', average)
except ZeroDivisionError:
    print('No subjects were entered, so the average cannot be worked out.')

print('--- Thank you ---')
Output
--- Marks Calculator ---
No subjects were entered, so the average cannot be worked out.
--- Thank you ---
1 · Graceful ending

The program finishes on its own terms. It says something a person can read and act on, and the lines after it still run — the closing message, the summary, the goodbye. Nothing is left half-done and nobody is shown a traceback they cannot use.

2 · Easier to find the fault

The handler sits around the exact lines that can fail, so the message can name the actual situation — 'no subjects were entered' rather than 'division by zero'. That points at the part of the program to look at, which is most of the work of debugging.

Key Takeaway
Handling an exception does not fix the problem. Dividing 250 by zero is still impossible. What changes is who decides what happens next — Python, with a traceback and a dead program, or you, with a sentence and the rest of the program still running.

2The shape of it

Two blocks
try:← the lines that might go wrong
average = total / subjects
except ZeroDivisionError:← what to do if that exact thing happens
print('...')

Both are ordinary blocks — a line ending in a colon, then an indented body, exactly like if, for and def. The except line names the exception it is prepared for.

3What Python actually does

The interesting part is that try behaves differently depending on whether anything goes wrong — so it is worth seeing both runs of the same program.

basic_catch.py
numerator = 10
denominator = 0

try:
    result = numerator / denominator
    print('Result:', result)
except ZeroDivisionError:
    print('Cannot divide by zero — please check the denominator.')

print('The program carries on.')
Output
Cannot divide by zero — please check the denominator.
The program carries on.

Notice what is not there: Result: never printed. The moment the division failed, Python abandoned the rest of the try block and jumped to the handler. Now the same program with a 2:

no_exception.py
numerator = 10
denominator = 2

try:
    result = numerator / denominator
    print('Result:', result)
except ZeroDivisionError:
    print('Cannot divide by zero — please check the denominator.')

print('The program carries on.')
Output
Result: 5.0
The program carries on.

This time the whole try block ran and the except block was skipped entirely. A handler is not a detour; it is a standby.

The rule in four lines
  1. 1. Run the try block, line by line.
  2. 2. If nothing goes wrong, skip except completely and carry on below.
  3. 3. If an exception is raised, abandon the rest of the try block at once.
  4. 4. If the except names that exception, run it — and then carry on below as if nothing happened.
Watch Out
Step 3 is the one that catches people out. The rest of the try block does not run. Not the next line, not the line after it. That is why you keep a try block short — every line in it is a line you are agreeing to skip.

4Getting Python's own message with as

Sometimes you want your friendly sentence and the technical detail — when you are debugging, or writing to a log. as gives the exception a name so you can print it:

message.py
try:
    marks = int('twelve')
except ValueError as e:
    print('Could not read that as a number.')
    print('Python said:', e)
Output
Could not read that as a number.
Python said: invalid literal for int() with base 10: 'twelve'
marks = int('twelve')

int() is happy to convert '12'. 'twelve' is a string of the right type holding a value it cannot use — which is exactly what ValueError means.

except ValueError as e:

as e puts the exception object into the name e. Any name works; e is the usual one.

print('Python said:', e)

Printing the exception prints its message — the same text that would have appeared on the last line of the traceback.

5Wrap the risky lines, not the whole program

It is tempting to put a try around everything and be done with it. Resist. A short try block does two things for you: it says clearly which line you expected to fail, and it means an unexpected failure somewhere else is not quietly reported as the problem you were guarding against.

Key Takeaway
A try block is a promise about which lines can fail. Keep it to the lines that genuinely can. Everything else — the prints, the sums that cannot go wrong, the tidying up — belongs outside it, where it will still run.
try_it.py

6Recap

try holds the risky lines

except says what to do if they go wrong. Both are ordinary colon-and-indent blocks.

Handling gives a graceful ending

A readable sentence instead of a traceback, and the lines below still run — so the program finishes properly.

It also points at the fault

The handler sits around the lines that can fail, so its message can name the real situation. That is where debugging starts.

The rest of the try block is abandoned

As soon as an exception is raised, Python jumps to the handler. Nothing else in the try runs.

No exception, no handler

If the try block finishes cleanly, the except block is skipped entirely.

as e gives you the message

print(e) shows the same text as the last line of the traceback. Useful while debugging.

✍️ Now write these yourself
  1. 1

    Run the marks calculator with subjects = 0, then with subjects = 5.

    Hint · Same program, two paths. The closing line prints either way.

  2. 2

    Put a second print after the division, inside the try, and check it does not run.

    Hint · The rest of the block is abandoned the moment it fails.

  3. 3

    Catch a ValueError from int('twelve') and print the message with as e.

    Hint · It is the same sentence the traceback would have ended with.

  4. 4

    Wrap a whole program in one try, then shrink it to the one risky line, and compare how each reads.

    Hint · The short one tells the reader which line you were worried about.

Quick Check

With denominator = 0, why does 'Result:' never print?

Quick Check

What happens to the except block when nothing goes wrong?

Quick Check

What does handling an exception actually change?