Tutorials Home   >   Core Programming Concepts   >   Custom Exceptions

Custom Exceptions

1. What Are Custom Exceptions?

Sometimes, the built-in exceptions like ValueError or IndexError aren’t enough to describe a specific problem in your program. In such cases, you can create your own exception class—these are called custom exceptions.

Why use them?

  • To make your error messages more meaningful.

  • To differentiate between different types of errors in complex programs.

  • To improve readability and maintainability of code.


2. Creating a Custom Exception

In Python, all exceptions must inherit from the built-in Exception class (or one of its subclasses).

Basic Example

# Define a custom exception
class NegativeAgeError(Exception):
"""Exception raised when age is negative."""
pass
# Use the custom exception
age = int(input(“Enter your age: “))
if age < 0:
raise NegativeAgeError(“Age cannot be negative!”)

Explanation:

  1. class NegativeAgeError(Exception): → This creates a new exception type.

  2. raise NegativeAgeError("message") → This triggers the exception if the condition is met.


Catching Custom Exceptions

Just like built-in exceptions, custom exceptions can be caught with try-except:

try:
age = int(input("Enter your age: "))
if age < 0:
raise NegativeAgeError("Age cannot be negative!")
except NegativeAgeError as e:
print("Custom Error:", e)

Output example:

Enter your age: -5
Custom Error: Age cannot be negative!

3. Adding More Details to Exceptions

You can add an __init__ method to include extra information, like the value that caused the error:

class NegativeAgeError(Exception):
def __init__(self, age, message="Age cannot be negative"):
self.age = age
self.message = message
super().__init__(self.message)
age = int(input(“Enter your age: “))
try:
if age < 0:
raise NegativeAgeError(age)
except NegativeAgeError as e:
print(f”Error: {e.message}. You entered: {e.age}“)

Output example:

Enter your age: -7
Error: Age cannot be negative. You entered: -7

This makes debugging much easier because you know exactly what went wrong.


4. Best Practices for Custom Exceptions

  1. Inherit from Exception:
    Avoid inheriting directly from BaseException.

  2. Use meaningful names:
    Example: InvalidTransactionError is clearer than just Error.

  3. Add extra info if needed:
    Include values or context that help debug.

  4. Keep them specific:
    Don’t create one generic exception for everything; it defeats the purpose.


5. Real-Life Example: Bank Transaction

Imagine a banking program:

class InsufficientFundsError(Exception):
pass
def withdraw(amount, balance):
if amount > balance:
raise InsufficientFundsError(f”Cannot withdraw {amount}. Balance is {balance}.”)
else:
balance -= amount
return balance

balance = 1000

try:
balance = withdraw(1500, balance)
except InsufficientFundsError as e:
print(e)

Output:

Cannot withdraw 1500. Balance is 1000.
  • The custom exception clearly communicates why the operation failed.