Chapter 9: Exception Handling
try/except/else/finally
Programs always encounter unexpected situations during runtime (file not found, network disconnected, user input errors...). Exception handling is like an "airbag" — it prevents the program from crashing completely due to a single error.
bash
# Complete exception handling structure
def safe_divide(a, b):
try:
result = a / b
except ZeroDivisionError:
print("❌ Error: Cannot divide by zero!")
return None
except TypeError as e:
print(f"❌ Type error: {e}")
return None
else:
# Executes when no exception occurs
print(f"✅ Calculation successful: {a} ÷ {b} = {result:.2f}")
return result
finally:
# Executes no matter what
print(" (Calculation process ended)")
print("=== Test 1: Normal ===")
safe_divide(10, 3)
print("\n=== Test 2: Division by zero ===")
safe_divide(10, 0)
print("\n=== Test 3: Type error ===")
safe_divide(10, "abc")bash
=== Test 1: Normal ===
✅ Calculation successful: 10 ÷ 3 = 3.33
(Calculation process ended)
=== Test 2: Division by zero ===
❌ Error: Cannot divide by zero!
(Calculation process ended)
=== Test 3: Type error ===
❌ Type error: unsupported operand type(s) for /: 'int' and 'str'
(Calculation process ended)Custom Exceptions
bash
# Custom exception class
class AgeError(ValueError):
def __init__(self, age, message="Age must be between 0-150"):
self.age = age
self.message = message
super().__init__(self.message)
def set_age(age):
if not isinstance(age, int):
raise TypeError("Age must be an integer")
if age < 0 or age > 150:
raise AgeError(age)
return f"Age set to: {age}"
# Test
try:
print(set_age(25))
print(set_age(-5))
except AgeError as e:
print(f"❌ Age error: {e.age} - {e.message}")
except TypeError as e:
print(f"❌ Type error: {e}")bash
Age set to: 25
❌ Age error: -5 - Age must be between 0-150⚠️ Note: ⚠️ Best practice: Never use bare
except:(without specifying an exception type) to catch all exceptions! This hides real bugs. Always specify the exact exception type.