Python Custom Exceptions

Let’s look at custom exceptions

  1. Notice

    A custom exception is a class derived from Exception. Raise it when your program needs to signal a specific failure.

  2. Try

    Follow the example, change its sample, and compare what happens.

  3. Check

    Explain the result and test your understanding.

Watch how it works

Focus on how the names, objects, and calculations change. We’ll inspect the printed output in the next section.

Explore the idea

Follow the code and watch its state change. Guided simulation.

Code
Python
class InvalidScore(Exception):
    pass
score = 3
try:
    if score < 0:
        raise InvalidScore("Score must be non-negative")
    print(score)
except InvalidScore as error:
    print(str(error))
Live state

Top-level scope

InvalidScore→Object 1
score→Object 2
Object 1 · typeclass InvalidScoreObject 2 · int3
This step

A custom exception is a class derived from Exception. Raise it when your program needs to signal a specific failure.

Picture custom exceptions

A custom exception is a class derived from Exception. Raise it when your program needs to signal a specific failure.

Image brief

Alt text
A diagram for Python Custom Exceptions. Instructions: class InvalidScore(Exception): pass score = 3 try: if score < 0: raise InvalidScore("Score must be non-negative") print(score) except InvalidScore as error: print(str(error)). Displayed result: 3. The final example bindings are InvalidScore --> object 1 (type); score --> object 2 (int). object 1: class InvalidScore; object 2: 3
Image generation prompt
Create a clean educational illustration for a Python programming lesson titled "Python Custom Exceptions". Teaching focus: A custom exception is a class derived from Exception. Raise it when your program needs to signal a specific failure. Depict exactly the relationships and labels in this reference diagram: EXAMPLE INSTRUCTIONS class InvalidScore(Exception): pass score = 3 try: if score < 0: raise InvalidScore("Score must be non-negative") print(score) except InvalidScore as error: print(str(error)) | v DISPLAYED RESULT 3 FINAL BINDINGS InvalidScore --> object 1 (type) score --> object 2 (int) object 1: class InvalidScore object 2: 3 Use a flat vector style, generous spacing, clear arrows and legible labels, with a restrained blue/teal palette on a plain background. The diagram must explain the programming idea accurately. Do not depict variables as boxes containing copied objects when they share a reference. Avoid mascots, decorative screenshots, logos, gradients and extra text. Landscape composition, approximately 3:2, suitable for a course card. Accessible description: A diagram for Python Custom Exceptions. Instructions: class InvalidScore(Exception): pass score = 3 try: if score < 0: raise InvalidScore("Score must be non-negative") print(score) except InvalidScore as error: print(str(error)). Displayed result: 3. The final example bindings are InvalidScore --> object 1 (type); score --> object 2 (int). object 1: class InvalidScore; object 2: 3

Follow the execution

Choose a different sample input, then follow every step through to the output. Before revealing it, predict what the program will display.

Execution workspace

Choose a sample and follow its execution. Guided simulation.

Code
Python
class InvalidScore(Exception):
    pass
score = 3
try:
    if score < 0:
        raise InvalidScore("Score must be non-negative")
    print(score)
except InvalidScore as error:
    print(str(error))
Live state

Top-level scope

InvalidScore→Object 1
score→Object 2
Object 1 · typeclass InvalidScoreObject 2 · int3
This step

The example has finished. Compare the final output with the values and references above.

Terminal
Output
3

What do you expect this program to print?

What does this example display?

class InvalidScore(Exception):
    pass
score = 3
try:
    if score < 0:
        raise InvalidScore("Score must be non-negative")
    print(score)
except InvalidScore as error:
    print(str(error))
What does this example display?
Choose one answer. You can try again.

Answer and explanation

3

Follow the printed values in order. The output is: 3

Which explanation matches what you learned?

Which explanation matches what you learned?
Choose one answer. You can try again.

Answer and explanation

A custom exception is a class derived from Exception. Raise it when your program needs to signal a specific failure.

A custom exception is a class derived from Exception. Raise it when your program needs to signal a specific failure.

Introduction to Python Custom Exceptions

In Python, not every error fits into the neat boxes of ValueError, IndexError, or TypeError. Sometimes, your program has its own rules — and when those are broken, you want your own error messages. That’s where custom exceptions come in.

Defining your own exception class helps you raise meaningful, specific errors that are easier to debug and maintain. This tutorial walks you through everything you need to know — from syntax to output — about creating and using custom exceptions in Python.

Why Use Custom Exceptions?

  • Readability: Custom exception names clearly explain what went wrong.
  • Modularity: Group specific behaviors under logical exception types.
  • Control: Handle different error types more granularly during exception handling.

How to Define a Custom Exception in Python

To define a custom exception, we subclass the built-in Exception class. Here's the basic syntax:

class MyCustomError(Exception):
    pass

This creates a new exception type called MyCustomError. Now, you can raise it using the raise keyword.

raise MyCustomError("Something went wrong in your custom logic!")

Basic Example: Custom Validation Exception

Let’s say you’re writing a function that only accepts even numbers. If the input is odd, you want to raise your own error.

class NotEvenNumberError(Exception):
    def __init__(self, number):
        super().__init__(f"The number {number} is not even.")

def check_even(n):
    if n % 2 != 0:
        raise NotEvenNumberError(n)
    return f"{n} is even."

# Test
print(check_even(10))
print(check_even(7))
10 is even.
Traceback (most recent call last):
  ...
NotEvenNumberError: The number 7 is not even.

How to Customize Exception Messages

You can go beyond basic text by passing arguments and overriding the __str__ method:

class LowBalanceError(Exception):
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount

    def __str__(self):
        return f"Transaction failed: Balance (${self.balance}) is less than amount (${self.amount})."
        
def withdraw(balance, amount):
    if amount > balance:
        raise LowBalanceError(balance, amount)
    return balance - amount

# Test
print(withdraw(100, 50))
print(withdraw(100, 150))
50
Traceback (most recent call last):
  ...
LowBalanceError: Transaction failed: Balance ($100) is less than amount ($150).

Important Guidelines When Creating Custom Exceptions

  • Always inherit from Exception or a subclass of it — never from BaseException unless you have a rare system-level reason.
  • Use descriptive names like UserNotFoundError or ConfigFileMissingError.
  • Consider using docstrings in your custom exception classes if they’ll be reused in larger applications.

Organizing Multiple Custom Exceptions

If you're building a large application, group related exceptions under a base class:

class AppError(Exception):
    """Base class for all application-specific errors."""
    pass

class ConfigError(AppError):
    pass

class DatabaseError(AppError):
    pass

When to Raise Custom Exceptions

Use them when your application rules are broken. Examples:

  • File not found in a specific directory even though the path exists
  • Invalid user input beyond what's handled by ValueError
  • When you need user-specific error feedback

How to Verify Custom Exceptions Work

You can test them using try/except blocks:

class LowBalanceError(Exception):
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount

    def __str__(self):
        return f"Transaction failed: Balance (${self.balance}) is less than amount (${self.amount})."
        
def withdraw(balance, amount):
    if amount > balance:
        raise LowBalanceError(balance, amount)
    return balance - amount

try:
    withdraw(20, 50)
except LowBalanceError as e:
    print("Caught:", e)
Caught: Transaction failed: Balance ($20) is less than amount ($50).

Conclusion

Custom exceptions give your code clarity and precision. Whether you’re building libraries, APIs, or full-stack apps, defining your own exceptions helps express intent and manage errors gracefully.

What to remember

Connect what you noticed in the example with the idea below.

Remember

A custom exception is a class derived from Exception. Raise it when your program needs to signal a specific failure.

Watch out for this idea

A custom exception must inherit from int.

This is the misconception to avoid.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Python Object-Oriented Programming →