Skip to content

Exception Handling

Exceptions are Python’s mechanism for signaling and handling errors at runtime. Code that might fail goes in a try block; except catches specific exception types and handles them; finally runs regardless of whether an exception occurred (cleanup code); else runs only if no exception was raised.

try:
result = 10 / 0
except ZeroDivisionError:
print("Can't divide by zero")
except (TypeError, ValueError) as e:
print(f"Bad input: {e}")
else:
print("No errors occurred") # only runs if try succeeded
finally:
print("This always runs") # cleanup, e.g. closing a file
# Raising your own exception
def withdraw(balance, amount):
if amount > balance:
raise ValueError("Insufficient funds")
return balance - amount

Using a bare except: (catching everything) β€” this silently swallows real bugs, including things like KeyboardInterrupt, making problems much harder to diagnose.

# Hides everything, including typos and bugs
try:
process(data)
except:
pass
# Catches only what you expect, and re-raises unknowns visibly
try:
process(data)
except ValueError as e:
log.warning(f"Skipping bad record: {e}")
  1. What’s wrong with a bare except: clause?

    AnswerIt catches every exception, including ones you didn't anticipate and system-level ones like KeyboardInterrupt, hiding real bugs instead of surfacing them.
  2. When does the finally block run?

    AnswerAlways β€” whether or not an exception was raised, and even if the try or except block returns or re-raises.
  3. What’s the difference between else and finally in a try statement?

    Answerelse runs only if no exception occurred in try; finally runs unconditionally, exception or not.