Raising and catching exceptions are essential concepts in Python for controlled error handling. Let’s explore how to raise custom exceptions and catch them using try-except blocks.
1. Raising Exceptions:
You can raise exceptions explicitly using the raise statement. This is useful when you want to signal an error in your code.
try:
    # Code that might raise an exception
    raise ValueError("This is a custom error.")
except ValueError as e:
    # Code to handle the raised exception
    print(f"Caught an exception: {e}")2. Custom Exception Classes:
Creating custom exception classes allows you to define application-specific exceptions by inheriting from the Exception class.
class CustomError(Exception):
    pass
try:
    # Code that might raise a custom exception
    raise CustomError("This is a custom error.")
except CustomError as ce:
    # Code to handle the custom exception
    print(f"Caught a custom exception: {ce}")3. Raising Exceptions Conditionally:
You can raise exceptions based on certain conditions in your code.
def divide_numbers(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero.")
    return a / b
try:
    result = divide_numbers(10, 0)
except ValueError as ve:
    print(f"Caught an exception: {ve}")4. Catching Multiple Exceptions:
When raising multiple types of exceptions, you can catch them selectively.
try:
    # Code that might raise different exceptions
    value = int("abc")
except ValueError:
    print("Caught a ValueError.")
except TypeError:
    print("Caught a TypeError.")
except Exception as e:
    print(f"Caught a generic exception: {e}")5. Reraising Exceptions:
You can reraise an exception within an except block to propagate it to the outer level.
try:
    # Code that might raise an exception
    raise ValueError("This is a custom error.")
except ValueError as e:
    # Code to handle the raised exception
    print(f"Caught an exception: {e}")
    # Reraising the exception
    raise6. Handling Unhandled Exceptions:
The sys module provides a way to handle unhandled exceptions using the excepthook function.
import sys
def custom_excepthook(exctype, value, traceback):
    print(f"Unhandled exception: {exctype.__name__}: {value}")
sys.excepthook = custom_excepthook
# Code that might raise an unhandled exception
result = 10 / 07. Conclusion:
Raising and catching exceptions are fundamental aspects of writing robust and error-tolerant Python code. Whether you are signaling specific errors in your application or handling unexpected issues, these concepts provide a structured approach to managing exceptions.
In the next sections, we’ll explore more advanced topics and practical applications of exception handling in Python.
