Topic 11 / 15
Exceptions & Error Handling
Errors Are Objects, Not Status Codes
When something goes wrong, Python raises an exception that travels up the call stack until something catches it — or the program exits with a traceback. Learn to read tracebacks bottom-up: the last line is the error, the lines above are the path that led there.
try / except
try:
age = int(input("Age: "))
except ValueError:
print("That's not a number.")Catch specific exceptions. A bare except: swallows everything — including typos in your own code and Ctrl-C — and turns bugs into silent mysteries:
try:
result = data["score"] / count
except KeyError:
print("no score field")
except ZeroDivisionError:
print("count is zero")
except (TypeError, ValueError) as e: # catch several, keep the object
print(f"bad data: {e}")else and finally
try:
f = open("data.json")
except FileNotFoundError:
print("missing file")
else:
# runs only if NO exception was raised
data = json.load(f)
finally:
# runs ALWAYS — cleanup belongs here
print("done")Raising Exceptions
def set_price(amount):
if amount < 0:
raise ValueError(f"price cannot be negative, got {amount}")
...Re-raise after logging with a bare raise, and chain causes with raise ... from e so the original traceback survives:
try:
charge(card)
except GatewayTimeout as e:
raise PaymentFailed("payment gateway unreachable") from eCustom Exceptions
Define your own for your domain — callers can then catch exactly what they care about:
class PaymentError(Exception):
"""Base class for payment failures."""
class CardDeclined(PaymentError):
pass
class InsufficientFunds(PaymentError):
def __init__(self, needed, available):
super().__init__(f"need ₹{needed}, have ₹{available}")
self.needed = needed
self.available = availableEAFP — the Python Philosophy
“Easier to Ask Forgiveness than Permission” — try the operation and handle failure, instead of pre-checking every condition:
# LBYL (look before you leap) — racy and verbose
if "score" in data and isinstance(data["score"], int):
value = data["score"]
# EAFP — pythonic
try:
value = int(data["score"])
except (KeyError, ValueError):
value = 0