⚡ Creating Custom Exceptions

Custom exceptions help you create specific error types for your applications. They make error handling more precise and provide better context about what went wrong.

# Simple custom exception
class ValidationError(Exception):
    pass

# Using custom exception
def validate_age(age):
    if age < 0:
        raise ValidationError("Age cannot be negative")
    if age > 150:
        raise ValidationError("Age seems unrealistic")
    return age

try:
    age = validate_age(-5)
except ValidationError as e:
    print(f"Validation failed: {e}")

🎯 Basic Custom Exceptions

Custom exceptions are classes that inherit from the built-in Exception class.

Simple Custom Exception

# Define custom exceptions
class InvalidEmailError(Exception):
    pass

class PasswordTooShortError(Exception):
    pass

# Use custom exceptions
def validate_email(email):
    if "@" not in email:
        raise InvalidEmailError("Email must contain @ symbol")
    return email

def validate_password(password):
    if len(password) < 8:
        raise PasswordTooShortError("Password must be at least 8 characters")
    return password

# Test validation
try:
    email = validate_email("invalid-email")
except InvalidEmailError as e:
    print(f"Email error: {e}")

try:
    password = validate_password("123")
except PasswordTooShortError as e:
    print(f"Password error: {e}")

Custom Exception with Additional Data

# Exception with extra information
class OutOfStockError(Exception):
    def __init__(self, product, available):
        self.product = product
        self.available = available
        message = f"Product '{product}' out of stock. Available: {available}"
        super().__init__(message)

# Use exception with data
def purchase_item(product, quantity):
    stock = {"apples": 5, "bananas": 0, "oranges": 3}
    available = stock.get(product, 0)
    
    if available < quantity:
        raise OutOfStockError(product, available)
    
    return f"Purchased {quantity} {product}"

try:
    result = purchase_item("bananas", 2)
except OutOfStockError as e:
    print(f"Error: {e}")
    print(f"Product: {e.product}")
    print(f"Available: {e.available}")

Exception Hierarchy

# Base custom exception
class APIError(Exception):
    pass

# Specific API exceptions
class AuthenticationError(APIError):
    pass

class RateLimitError(APIError):
    pass

class ServerError(APIError):
    pass

# Function that raises different errors
def api_call(status_code):
    if status_code == 401:
        raise AuthenticationError("Invalid credentials")
    elif status_code == 429:
        raise RateLimitError("Too many requests")
    elif status_code >= 500:
        raise ServerError("Server error occurred")
    return "API call successful"

# Handle different error types
try:
    result = api_call(429)
except AuthenticationError:
    print("Please check your credentials")
except RateLimitError:
    print("Please wait before making more requests")
except APIError:
    print("General API error occurred")

📋 Custom Exception Patterns

PatternPurposeExample
SimpleBasic custom errorclass CustomError(Exception): pass
With messageCustom error messagesuper().__init__(message)
With dataStore additional infoself.code = code
HierarchyRelated error typesclass SubError(BaseError):

🔧 Advanced Custom Exceptions

Exception with Multiple Attributes

class ValidationError(Exception):
    def __init__(self, field, value, message):
        self.field = field
        self.value = value
        self.message = message
        super().__init__(f"{field}: {message} (got: {value})")

def validate_user_data(name, age, email):
    if not name:
        raise ValidationError("name", name, "Name cannot be empty")
    if age < 0:
        raise ValidationError("age", age, "Age cannot be negative")
    if "@" not in email:
        raise ValidationError("email", email, "Invalid email format")

try:
    validate_user_data("", 25, "test@email.com")
except ValidationError as e:
    print(f"Validation failed:")
    print(f"  Field: {e.field}")
    print(f"  Value: {e.value}")
    print(f"  Message: {e.message}")

Exception with Error Codes

class BusinessError(Exception):
    def __init__(self, code, message):
        self.code = code
        self.message = message
        super().__init__(f"Error {code}: {message}")

# Define specific error codes
INSUFFICIENT_FUNDS = 1001
ACCOUNT_LOCKED = 1002
INVALID_TRANSACTION = 1003

def process_payment(amount, balance, account_status):
    if account_status == "locked":
        raise BusinessError(ACCOUNT_LOCKED, "Account is locked")
    if amount > balance:
        raise BusinessError(INSUFFICIENT_FUNDS, "Not enough funds")
    if amount <= 0:
        raise BusinessError(INVALID_TRANSACTION, "Invalid transaction amount")

try:
    process_payment(100, 50, "active")
except BusinessError as e:
    print(f"Payment failed: {e}")
    print(f"Error code: {e.code}")
    
    if e.code == INSUFFICIENT_FUNDS:
        print("Consider making a smaller payment")
    elif e.code == ACCOUNT_LOCKED:
        print("Contact support to unlock account")

Re-raising Exceptions

class DatabaseError(Exception):
    pass

class ConnectionError(DatabaseError):
    pass

def connect_to_database():
    # Simulate connection error
    raise ConnectionError("Cannot connect to database")

def get_user_data(user_id):
    try:
        connect_to_database()
        return {"id": user_id, "name": "User"}
    except ConnectionError:
        print("Database connection failed, using cache")
        raise  # Re-raise the exception

try:
    user = get_user_data(123)
except DatabaseError as e:
    print(f"Database operation failed: {e}")

📊 Exception Organization Reference

Exception Naming Conventions

TypeNaming PatternExample
General errors[Purpose]ErrorValidationError
Specific conditions[Condition]ErrorOutOfStockError
API/Network[Service]ErrorAPIError
Data processing[Data]ErrorParseError

Exception Hierarchy Best Practices

LevelPurposeExample
BaseCommon error typeclass APIError(Exception)
CategorySpecific error groupclass AuthError(APIError)
SpecificExact error conditionclass InvalidTokenError(AuthError)

🎯 Key Takeaways

🚀 What's Next?

Learn debugging techniques to find and fix issues in your code effectively.

Continue to: Debug Code

Was this helpful?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent