An Introduction to the Art of Computer Programming Using Python in the Age of Generative AI

X. Error and Exception Handling

Errors should never pass silently.
Unless explicitly silenced.
Tim Peters, Zen of Python

Introduction to Error Handling

Error handling is a crucial part of programming, ensuring that your program can gracefully handle unexpected situations. In Python, error handling is done through the use of exceptions. Exception handling allows you to manage errors in a controlled manner, improving the robustness and reliability of your programs.

Basic Exception Handling

The try and except blocks are used to catch and handle exceptions. If an error occurs within the try block, the except block catches the exception and allows the program to continue.


try:
    result = 10 / 0
except ZeroDivisionError:
    result = "undefined"
print(result)
        

Handling Multiple Exceptions

A single try block can be followed by multiple except blocks to handle different types of exceptions. This allows you to respond appropriately to different error conditions.


try:
    list = [1, 2, 3]
    result = list[5]
except IndexError:
    result = "Index error"
except Exception as e:
    result = str(e)
print(result)
        

The Else and Finally Clauses

The else block runs if the try block did not throw an exception. The finally block runs no matter what, typically used for cleanup operations.


try:
    result = 10 / 2
except ZeroDivisionError:
    print("Divided by zero!")
else:
    print("Division successful!")
finally:
    print("This runs no matter what.")
        

Raising Exceptions

You can raise your own exceptions using the raise keyword. This is useful for signaling specific error conditions in your code.


def divide(a, b):
    if b == 0:
        raise ValueError("You can't divide by zero!")
    return a / b

try:
    result = divide(10, 0)
except ValueError as ve:
    result = str(ve)
print(result)
        

Custom Exception Classes

You can create custom exception classes to handle specific error conditions in your application. This can make your error handling more granular and meaningful.


class NegativeValueError(Exception):
    pass

def sqrt(value):
    if value < 0:
        raise NegativeValueError("Cannot compute the square root of a negative number!")
    return value ** 0.5

try:
    result = sqrt(-9)
except NegativeValueError as nve:
    result = str(nve)
print(result)
        

Logging Exceptions

Logging exceptions is a best practice for understanding and diagnosing problems in your programs. The logging module in Python provides a flexible framework for outputting log messages from Python programs.


import logging

logging.basicConfig(level=logging.ERROR)

def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError as e:
        logging.error("Attempted to divide by zero.")
        return "undefined"

result = divide(10, 0)
print(result)
        

Prompting Generative AI for Meaningful Error Handling

Using AI can greatly enhance your ability to effectively handle errors and exceptions.

Example Prompt:
Generate a Python function that reads from a file and handles file-related errors gracefully.

Resulting AI-generated code:


def read_file(file_path):
    try:
        with open(file_path, 'r') as file:
            content = file.read()
        return content
    except FileNotFoundError:
        return "File not found."
    except PermissionError:
        return "Permission denied."
    except Exception as e:
        return f"An error occurred: {str(e)}"

file_content = read_file("example.txt")
print(file_content)
        
Back to Home