Custom Exceptions
Overview
While Python provides excellent built-in exceptions like ValueError and TypeError, relying solely on them makes your domain logic messy. If an API request fails, a generic ValueError doesn't convey context. By defining Custom Exceptions, you create a self-documenting, hierarchical error structure that makes debugging complex backend systems significantly easier.
Syntax
# Custom exceptions MUST inherit from Exception
class InsufficientFundsError(Exception):
def __init__(self, balance, amount):
# Pass a detailed message to the base class
super().__init__(f"Declined: Tried to withdraw {amount}, but balance is {balance}")
# Store custom attributes for programmatic handling later
self.balance = balance
self.amount = amount
# Raising the exception based on business logic
current_balance = 50
withdrawal = 100
if withdrawal > current_balance:
raise InsufficientFundsError(current_balance, withdrawal)Common Pitfalls
Inheriting from
BaseExceptioninstead ofException.BaseExceptionis the grand-parent class reserved for system-exiting signals (like KeyboardInterrupt). Custom application logic should always branch fromException.
Interview Questions
How do you trigger an exception manually in your code?
By using the raise keyword, followed by an instance of the exception class. For example: raise ValueError('Invalid formatting').
Real-World Example
Implementing structured HTTP-like domain errors in a backend architecture.
class UserNotFoundError(Exception):
pass
def fetch_user_profile(user_id):
user = db_lookup(user_id)
if not user:
raise UserNotFoundError(f"User {user_id} does not exist in the database.")
return userCheck Your Knowledge
Test your understanding of Custom Exceptions with these quick questions.