Latticework

Command Palette

Search for a command to run...

Python

Exceptions

14 min

Explanation

When something goes wrong, Python raises an exception — normally that crashes your program with a traceback. try/except lets you catch it and decide what to do instead of crashing.

try:
    result = 10 / 0
except ZeroDivisionError:
    result = None
    print("can't divide by zero")

Only wrap the specific line(s) that might fail — putting an entire large function inside one try block makes it hard to tell which line actually raised, when something goes wrong later.

Try it

Catching a specific exception type (IndexError) means a genuinely different bug elsewhere in the function won't get silently swallowed by an overly broad except.

Loading editor…
Explanation

Always catch the narrowest exception type that matches what you expect to go wrong — ValueError for a bad conversion, KeyError for a missing dict key, ZeroDivisionError for division, IndexError for an out-of-range index. A bare except: (or except Exception:, which is only slightly narrower) catches everything, including bugs you didn't anticipate — that turns a loud crash (which tells you something's wrong) into a silent wrong answer, which is much harder to debug later.

def to_int(s):
    try:
        return int(s)
    except ValueError:
        return None
Exercise

Write a function `safe_divide(a, b)` that returns `a / b`, or the string 'undefined' if `b` is 0 — catch the specific exception `/` raises, don't check `b == 0` beforehand.

Exercise

Write a function `parse_int_list(strings)` that converts each string in `strings` to an int, skipping any that fail to convert, and returns the successfully-converted ints in order.

Quiz

What's the risk of a bare `except:` (with no exception type) compared to `except Exception:`?

Checkpoint

You can catch specific exception types with try/except and know why overly broad exception handling is a real bug risk, not just a style preference.