【Introduction to Python Exception Handling】 A Detailed Guide from Basics to Best Practices

1. What is an Exception in Python?

An exception in Python is a type of error that occurs during program execution. Normally, a program runs sequentially from top to bottom, but if an error occurs under certain conditions, execution is interrupted, and an exception is raised.
For example, attempting to divide by zero results in a ZeroDivisionError, and accessing an index that does not exist in a list raises an IndexError.

1.1 Common Types of Exceptions

Python has many built-in exceptions. Here are some common examples:

  • ValueError: Raised when a function receives an argument of the correct type but an inappropriate value.
  • TypeError: Raised when an operation or function is applied to an object of an inappropriate type.
  • IndexError: Raised when trying to access an index that is out of range in a sequence (e.g., a list).
  • ZeroDivisionError: Raised when attempting to divide by zero.

These exceptions provide useful diagnostic information when unexpected errors occur during program execution.

2. Basic Exception Handling with try and except

Python allows exception handling using try and except. This prevents the program from crashing due to an error, allowing it to continue running even after an exception is encountered.

2.1 Basic Syntax

The try block contains code that may cause an error, while the except block defines how to handle the error if it occurs.

try:
    result = 10 / 0
except ZeroDivisionError:
    print("You cannot divide by zero.")

In this example, if a ZeroDivisionError occurs, the except block executes and prints “You cannot divide by zero.”

2.2 Handling Multiple Exceptions

If you need to handle different types of exceptions separately, you can use multiple except blocks.
For example, you can handle NameError and TypeError differently:

try:
    print(a)
except NameError:
    print("Variable 'a' is not defined.")
except TypeError:
    print("An invalid type was used.")

In this code, since a is not defined, a NameError occurs, and the corresponding message is displayed.

侍エンジニア塾

3. Handling Multiple Exceptions in a Single except Block

If your program may encounter multiple types of exceptions, you can handle them together in a single except block.

3.1 Using a Tuple to Handle Multiple Exceptions

You can specify multiple exception types in a single except block by using a tuple:

try:
    num = int(input("Enter a number: "))
    result = 10 / num
except (ValueError, ZeroDivisionError):
    print("Invalid input or attempt to divide by zero.")

In this example, if the user inputs an invalid value or attempts to divide by zero, the program handles both cases together and prints “Invalid input or attempt to divide by zero.”

3.2 Using Parent Classes to Handle Multiple Exceptions

The Exception class is the parent class of most built-in exceptions.
You can catch all exceptions using this class, but it should be used with caution since it catches a broad range of errors.

try:
    # Code that may raise an error
except Exception as e:
    print("An error occurred:", e)

This method catches any exception and prints a message. However, it is recommended to handle specific exceptions whenever possible for better error handling.


4. Raising Exceptions with raise

Sometimes, you may need to manually raise an exception if certain conditions are not met.
This can be done using the raise statement.

4.1 How to Use raise

The following example raises a ValueError if a negative value is passed:

def check_value(value):
    if value < 0:
        raise ValueError("Negative values are not allowed.")
    return value

try:
    result = check_value(-1)
except ValueError as e:
    print(e)

In this example, since -1 is passed to the check_value function, a ValueError is raised, displaying the message: "Negative values are not allowed."

4.2 Advanced Usage of raise

The raise statement can also be used to define custom exception classes.
By creating custom exceptions and raising them under specific conditions, you can make error handling more flexible.

5. Retrieving Exception Information

When an exception occurs, retrieving detailed information can help diagnose and debug issues.
Using the as clause in the except block allows you to capture the exception object.

5.1 Using the as Clause

The following example captures the exception object as e and displays its message:

try:
    result = 10 / 0
except ZeroDivisionError as e:
    print("An error occurred:", e)

If a ZeroDivisionError occurs, this code prints:
**"An error occurred: division by zero"**
The exception object contains details such as the exception type and error message.

5.2 Utilizing Exception Objects

Exception objects are not only useful for displaying error messages but also for logging errors and implementing additional handling for specific errors.
For example, you can write error messages to a log file to help with debugging later.

6. Best Practices for Exception Handling

Effective exception handling improves program robustness and reliability.
Here are some best practices for handling exceptions in Python.

6.1 Catch Specific Exceptions

Whenever possible, catch specific exceptions rather than using a broad Exception handler.
Catching exceptions like ValueError or TypeError ensures clearer and more intentional error handling.

6.2 Log Exceptions

Logging error messages makes it easier to identify issues later.
In large-scale applications, keeping a record of exceptions is crucial for debugging and maintenance.

6.3 Implement Graceful Degradation

Ensure that exceptions do not cause the entire program to crash.
By displaying user-friendly error messages or providing alternative actions, you can improve the program’s reliability.

6.4 Avoid Swallowing Exceptions

Avoid catching exceptions and doing nothing.
This makes debugging difficult and can lead to unexpected behavior.
At a minimum, log error messages or take appropriate action.

6.5 Use the finally Block

The finally block is executed regardless of whether an exception occurs.
It is useful for closing files, releasing resources, or performing necessary cleanup tasks.

try:
    file = open("example.txt", "r")
    # Read the file
except FileNotFoundError:
    print("File not found.")
finally:
    file.close()

In this example, even if opening the file fails, the finally block ensures that the file is properly closed.

侍エンジニア塾

7. Summary

Exception handling in Python is essential for ensuring program reliability and managing errors effectively.
By using try and except to catch errors and raising custom exceptions with raise, you can improve code flexibility and maintainability.

  • We learned what exceptions are and explored common types of exceptions.
  • We covered how to handle exceptions using try and except.
  • We looked at handling multiple exceptions in a single except block.
  • We learned how to raise exceptions using the raise statement.
  • We discussed retrieving exception objects for detailed error information.
  • Finally, we explored best practices for effective error handling.

Exception handling is a crucial technique for ensuring software reliability.
By applying these techniques, you can develop robust and user-friendly Python applications.