Python: Handling Exceptions with Try/Except/Else/Finally

Updated: July 15, 2023 By: Wolf Post a comment

What is the Point?

In Python, you can handle exceptions using the try/except/else/finally statements. These statements provide a way to catch and handle exceptions, execute specific code when no exceptions occur, and perform cleanup operations regardless of whether an exception is raised or not.

Here’s the general syntax:

try:
    # Code that might raise an exception
    # ...
except ExceptionType1:
    # Code to handle ExceptionType1
    # ...
except ExceptionType2:
    # Code to handle ExceptionType2
    # ...
else:
    # Code to execute if no exceptions were raised
    # ...
finally:
    # Code that always executes, regardless of exceptions
    # ...

Where:

  • try: Starts the try block where the code that might raise an exception is placed.
  • except: Specifies the exception type(s) to catch and the corresponding code to handle the exception.
  • else: Optional block that executes if no exceptions were raised in the try block.
  • finally: Optional block that always executes, regardless of whether an exception occurred or not.

For more clarity, see the following examples.

Examples

Basic Error Handling

This example demonstrates the basic usage of try and except. It attempts to perform a division by zero operation and catches the ZeroDivisionError to handle the exception gracefully:

try:
    x = 10 / 0
except ZeroDivisionError:
    print("Cannot divide by zero.")

Output:

Cannot divide by zero.

Handling Multiple Exception Types

n this example, multiple except blocks are used to handle different types of exceptions. It prompts the user for input, performs a division operation, and handles ValueError and ZeroDivisionError separately:

try:
    num = int(input("Enter a number: "))
    result = 10 / num
    print("Result:", result)
except ValueError:
    print("Invalid input. Please enter a valid integer.")
except ZeroDivisionError:
    print("Error: Cannot divide by zero.")

The output depends on your input. If you enter a non-integer (a string or a float), you will receive this message:

Invalid input. Please enter a valid integer.

If the program is fed with zero, you’ll see this:

Error: Cannot divide by zero.

Otherwise, no exception will be raised.

Else Block for Successful Execution

The else block is executed when no exceptions occur within the try block. This example tries to open a file and, if successful, prints a success message before closing the file:

try:
    file = open("example.txt", "r")
except IOError:
    print("Error: Failed to open the file.")
else:
    print("File opened successfully.")
    file.close()

If you don’t have the file named example.txt in the same directory as your Python script, this message will appear:

Error: Failed to open the file.

Cleanup Operations with Finally

The finally block is executed regardless of whether an exception occurred or not. This example attempts to access an element outside the range of a list, catches the IndexError, and then executes a cleanup operation:

try:
    data = [1, 2, 3]
    result = data[4]
except IndexError:
    print("Error: Index out of range.")
finally:
    print("Cleanup: Closing resources.")
    data.clear()

Output:

Error: Index out of range.
Cleanup: Closing resources.

Raising Custom Exception

This is the last example in this article. It showcases how to raise and handle custom exceptions. It prompts the user for their age, checks if it is negative, and raises a custom exception if so. The custom exception is then caught, and its message is printed.

class NegativeAgeError(Exception):
    def __init__(self, age):
        self.age = age
        super().__init__(f"Invalid age: {age}. Age cannot be negative.")

def validate_age(age):
    if age < 0:
        raise NegativeAgeError(age)
    # Additional validation logic if needed

try:
    user_age = int(input("Enter your age: "))
    validate_age(user_age)
    print("Age validation successful!")
except NegativeAgeError as e:
    print(e)
except ValueError:
    print("Invalid input. Please enter a valid age.")

The custom exception NegativeAgeError is defined by inheriting from the base Exception class. The Exception class has an init method to initialize the exception object with the invalid age value. The exception message is customized to include the specific age that caused the error.

The validate_age function is responsible for validating the age and raising the NegativeAgeError if it is negative.

When prompting the user for their age, the input is validated using the validate_age function. If the age is negative, the NegativeAgeError is raised and caught in the except block, where the exception message is printed. Additionally, a separate except block handles ValueError if the user enters an invalid input (such as some text like “ABC”, “XYZ”, etc).