How & why to create custom exceptions in python

img
Code B's lead backend programmer- Bhavesh Gawade
Bhavesh GawadeSoftware Engineerauthor linkedin
Published On
Updated On
Table of Content
up_arrow

Python’s robust error handling system is one of the language’s strengths. By using exceptions, you can write cleaner, more maintainable code that handles errors gracefully. In this blog, we’ll dive into what exceptions are, explore the types of exceptions in Python including custom exceptions and learn why and how to create and use them in your projects.

What are Exceptions?

try catch block in python .png

Exceptions are events that occur during the execution of a program that disrupt its normal flow. They are Python’s way of signaling that something unexpected has happened. When an error occurs, Python raises an exception, which, if not handled, can cause the program to crash. However, with proper exception handling, you can catch these errors and decide how your program should respond.

Types of Exceptions

types of exceptions.png

1. Built-in Exceptions by Python

Python comes with a rich set of built-in exceptions. Some common ones include:

  • ValueError: Raised when a function receives an argument of the correct type but an inappropriate value.
  • TypeError: Triggered when an operation or function is applied to an object of inappropriate type.
  • IndexError: Raised when attempting to access an index that is out of range in a sequence.
  • KeyError: Occurs when a dictionary key is not found.
  • FileNotFoundError: Triggered when a file or directory is requested but does not exist.

These exceptions help catch common errors, but they might not always capture the specific nuances of your application’s logic.

2. Custom Exceptions

Custom exceptions allow you to define errors that are specific to your application. By creating your own exception classes, you can signal and handle conditions that are unique to your program’s domain. This makes your code easier to understand and maintain, as you can provide more descriptive error messages tailored to your use case.

Why Create Custom Exceptions?

Creating custom exceptions in Python can be beneficial for several reasons:

  • Clarity and Readability: Custom exceptions can make your code more readable by clearly indicating what went wrong in a context-specific manner.
  • Specific Error Handling: They allow you to catch and handle errors that are unique to your application, instead of relying solely on general built-in exceptions.
  • Encapsulation: By encapsulating error conditions in custom exceptions, you keep error-handling logic separate from business logic, making your code cleaner.
  • Debugging: They provide more specific error messages which can greatly aid in debugging and troubleshooting issues in your code.

How to Create Custom Exceptions?

Creating a custom exception in Python is straightforward. Typically, you create a new exception by subclassing the built-in Exception class (or another appropriate built-in exception). Here’s a simple example:

class MyCustomError(Exception):
"""Exception raised for custom errors in the application."""
def __init__(self, message):
self.message = message
super().__init__(self.message)

In this example, MyCustomError is a custom exception that takes a message argument. By subclassing Exception, it inherits all the standard behaviors of Python exceptions.

How to Use Custom Exceptions?

Let’s put our custom exception into action.

Custom Exceptions for Inventory Management

In a retail or warehouse management system, handling errors like out-of-stock items, invalid product requests, or exceeding purchase limits is crucial. Let's define some custom exceptions:

class ProductNotAvailableError(Exception):
"""Raised when the requested product is not in stock."""
def __init__(self, product_name):
super().__init__(f"Error: '{product_name}' is currently unavailable in stock.")

class InvalidItemCodeError(Exception):
"""Raised when a product code is not found in inventory."""
def __init__(self, item_code):
super().__init__(f"Error: '{item_code}' is not a valid item code.")

class ExceededPurchaseLimitError(Exception):
"""Raised when a purchase request exceeds the allowed quantity."""
def __init__(self, product_name, max_limit):
super().__init__(f"Error: Purchase limit exceeded. You can only buy up to {max_limit} units of '{product_name}'.")

Implementing the Inventory System

We will create an InventorySystem class to manage products and handle these exceptions.

class InventorySystem:
def __init__(self):
self.items = {
'A101': {'name': 'Wireless Headphones', 'stock': 8, 'purchase_limit': 3},
'A102': {'name': 'Gaming Mouse', 'stock': 0, 'purchase_limit': 2},
'A103': {'name': 'Mechanical Keyboard', 'stock': 5, 'purchase_limit': 1},
}

def purchase_item(self, item_code, quantity):
if item_code not in self.items:
raise InvalidItemCodeError(item_code)

product = self.items[item_code]

if product['stock'] == 0:
raise ProductNotAvailableError(product['name'])

if quantity > product['purchase_limit']:
raise ExceededPurchaseLimitError(product['name'], product['purchase_limit'])

if quantity > product['stock']:
raise ProductNotAvailableError(product['name'])

product['stock'] -= quantity
print(f"Purchase successful! {quantity} unit(s) of '{product['name']}' bought. Remaining stock: {product['stock']}.")

Using the Inventory System

Now, let's handle different scenarios using a try-except block:

inventory = InventorySystem()

try:
inventory.purchase_item('A101', 2) # Valid purchase
inventory.purchase_item('A102', 1) # Out of stock
inventory.purchase_item('A103', 2) # Exceeds limit
inventory.purchase_item('B200', 1) # Invalid product code
except (ProductNotAvailableError, InvalidItemCodeError, ExceededPurchaseLimitError) as e:
print(e)

Expected Output

Purchase successful! 2 unit(s) of 'Wireless Headphones' bought. Remaining stock: 6.
Error: 'Gaming Mouse' is currently unavailable in stock.

Best Practices for Naming Custom Exceptions

When naming custom exceptions, follow these best practices:

  • Suffix with "Error": This convention (e.g., ValidationError, ConnectionError) immediately signals that the class represents an error condition.
  • Be Descriptive: Choose names that clearly indicate the error's nature. Avoid vague names that don’t convey useful information.
  • Consistency: Maintain a consistent naming pattern throughout your codebase, which helps other developers understand and maintain the code.
  • Documentation: Include a docstring that describes when the exception is raised and any additional context that may help with debugging.

Conclusion

Custom exceptions are a powerful tool in Python that allow you to write more expressive, maintainable, and robust error-handling code. By understanding the built-in exceptions and knowing when to create your own, you can handle unique error conditions gracefully. With clear naming conventions and proper documentation, custom exceptions can significantly improve the overall quality and clarity of your code.

Happy coding, and may your exceptions be ever meaningful!👋

FAQs

1. Why should I create custom exceptions instead of using built-in ones?
Image 2
2. Can I create multiple custom exceptions in the same program?
Image 2
3. Can a custom exception inherit from another custom exception?
Image 2
4. Can I include additional attributes in my custom exception?
Image 2
5. What are some best practices for writing custom exceptions?
Image 2


Software Engineer
Profile
Dhaval Gala
LinkedInGitHub
Co-Founder
React Native
Python
AWS
Profile
Kuldeep Mane
LinkedInGitHub
Software Engineer
Python
.NET
Software Developers
Profile
Amit Yadav
LinkedInGitHub
Software developer
React Native
Python
Angular
Schedule a call now
Start your offshore web & mobile app team with a free consultation from our solutions engineer.

We respect your privacy, and be assured that your data will not be shared