CodeOath
← All posts
Python70 min total · 18 parts

Python Fundamentals for Interviews: Data Structures, Comprehensions, and Gotchas

Contents — Part 12 of 18: Exception Handling
Part 12 of 18 · ~1 min

Exception Handling

try:
    result = risky_operation()
except ValueError as e:
    print(f"Bad value: {e}")
except (TypeError, KeyError) as e:
    print(f"Type or key issue: {e}")
else:
    print("Ran only if no exception was raised")
finally:
    print("Always runs — cleanup goes here")

Order matters: except clauses are checked top to bottom, and the first matching one wins — a broad except Exception placed before a specific except ValueError would swallow the ValueError before the more specific handler ever saw it, so specific exceptions belong before general ones.

Bare except: is almost always wrong

try:
    do_something()
except:  # catches EVERYTHING, including KeyboardInterrupt and SystemExit
    pass

A bare except: (or except BaseException:) catches signals meant to actually stop the program — KeyboardInterrupt (Ctrl+C) and SystemExit — silently swallowing them along with real bugs. except Exception: is the correct "catch almost anything" clause, since Exception deliberately excludes those two.

Custom exceptions and re-raising

class InsufficientFundsError(Exception):
    def __init__(self, balance, amount):
        super().__init__(f"Cannot withdraw {amount}, balance is {balance}")
        self.balance = balance
        self.amount = amount

try:
    withdraw(account, 500)
except InsufficientFundsError as e:
    log.error("withdrawal failed")
    raise  # re-raises the SAME exception with its original traceback intact

raise with no argument inside an except block re-raises the exception currently being handled, preserving its original traceback — raise e instead loses some of that context (it looks like the exception originated at this raise line, not its actual source). Custom exception classes that carry structured data (self.balance, self.amount above) let calling code inspect why something failed programmatically instead of parsing an error string.