Python Exception Handling

They’re basically errors that occur during program execution. In other words, when your code goes rogue and starts acting like a wild animal in the jungle. Chill out, don’t worry, because we have exception handling to save us from these chaotic situations!

Now how Python handles exceptions. When an error occurs, it raises an exception object that contains information about what went wrong. This is where our trusty try-except block comes in handy. The try block executes the code we want to run and if everything goes smoothly, great! But if an exception is raised during execution, control jumps over to the except block which handles the error.

Here’s a simple example:

# This script is using a try-except block to handle potential errors that may occur during execution.

# The try block executes the code we want to run and if everything goes smoothly, great! 
# But if an exception is raised during execution, control jumps over to the except block which handles the error.

# Here's a simple example:

# The script prompts the user to enter a number and converts it to an integer.
# If the input is not a valid integer, a ValueError exception is raised and the except block is executed.
# If the input is a valid integer, the code in the try block is executed.

# The try block also performs a division operation with the input number.
# If the input is 0, a ZeroDivisionError exception is raised and the except block is executed.
# If the input is not 0, the code in the try block is executed.

# The else block is executed if no exceptions are raised during the execution of the try block.
# It prints the result of the division operation.

try:
    # Prompts the user to enter a number and converts it to an integer.
    x = int(input("Enter a number: "))
    # Performs a division operation with the input number.
    10 / x
# Handles a ValueError exception if the input is not a valid integer.
except ValueError:
    print("Invalid input!")
# Handles a ZeroDivisionError exception if the input is 0.
except ZeroDivisionError:
    print("Cannot divide by zero!")
# Executes if no exceptions are raised during the execution of the try block.
else:
    # Prints the result of the division operation.
    print("Result:", 10/x)

In this example, we’re using the try-except block to handle two different types of exceptions. If a ValueError is raised (e.g., if the user enters a string instead of an integer), control jumps over to the except block that handles it. Similarly, if a ZeroDivisionError is raised (i.e., we’re trying to divide by zero), control also jumps over to the second except block. If no exceptions are raised during execution, control goes through the else block which executes after all try-except blocks have been checked.

Now inheritance and subclassing built-in exception types in Python. This is where things get a bit more advanced but also very useful! By creating custom exception classes that inherit from existing ones, we can add our own functionality to handle errors in a specific way for our program. For example:

# Creating a custom exception class that inherits from the built-in ValueError class
class MyCustomException(ValueError):
    # Defining the constructor method with the parameter 'message'
    def __init__(self, message):
        # Assigning the value of 'message' to the instance variable 'message'
        self.message = message
    
    # Defining the string representation of the exception
    def __str__(self):
        # Returning a formatted string with the custom message
        return f"My custom exception occurred: {self.message}"

In this example, we’re creating a new exception class called MyCustomException that inherits from the built-in ValueError type. This allows us to add our own functionality and behavior when an error occurs in our program using this specific exception type. When an instance of this custom exception is raised during execution, it will behave like any other ValueError object but with additional information provided by our __init__ method.

SICORPS