Skip to Content
Course content

7.1 Understanding Exceptions

Exceptions are events that disrupt the normal flow of a program’s execution. In Python, exceptions are used to handle errors or other exceptional conditions that occur during the execution of the program. Understanding how exceptions work and how to handle them is an important part of writing robust Python programs.

1. What Are Exceptions?

An exception is an error that occurs during the execution of a program. It can be a runtime error, such as dividing by zero, trying to access an undefined variable, or attempting to read a file that doesn't exist. When an exception occurs, the normal flow of execution is stopped, and Python looks for a block of code (exception handler) to deal with the issue.

2. Types of Exceptions

Python has a variety of built-in exceptions, each representing a different type of error. Some common exceptions include:

  • ZeroDivisionError: Raised when dividing a number by zero.
  • ValueError: Raised when a function receives an argument of the correct type but an inappropriate value.
  • FileNotFoundError: Raised when trying to open a file that doesn’t exist.
  • IndexError: Raised when trying to access an index that is out of range for a list or other sequence.
  • KeyError: Raised when trying to access a dictionary with a key that doesn’t exist.
  • TypeError: Raised when an operation or function is applied to an object of inappropriate type.

Each exception provides useful information about the error, such as the type of exception and where the error occurred.

3. Handling Exceptions with try, except

In Python, exceptions can be handled using the try and except blocks. Here's the basic structure of exception handling:

try:
    # Code that might raise an exception
    result = 10 / 0  # Example: division by zero
except ZeroDivisionError as e:
    # Code that handles the exception
    print(f"Error: {e}")

In the above example:

  • The try block contains the code that might raise an exception (in this case, dividing by zero).
  • The except block catches the exception and handles it by printing an error message.

4. Multiple Except Blocks

You can handle multiple types of exceptions by using multiple except blocks. This allows you to provide different responses to different types of exceptions.

try:
    x = int(input("Enter a number: "))
    y = 10 / x
except ValueError as e:
    print(f"Invalid input: {e}")
except ZeroDivisionError as e:
    print(f"Cannot divide by zero: {e}")

In this case:

  • If the user enters a non-numeric input, the ValueError block will be executed.
  • If the user enters zero, the ZeroDivisionError block will handle it.

5. Handling Multiple Exceptions in One Block

Python allows you to catch multiple exceptions in a single except block by specifying them as a tuple. This can simplify the code when you need to handle multiple exceptions in the same way.

try:
    value = int(input("Enter a number: "))
    result = 10 / value
except (ValueError, ZeroDivisionError) as e:
    print(f"Error: {e}")

This code handles both ValueError and ZeroDivisionError in a single except block.

6. The else Block

In addition to try and except, Python also supports an optional else block. The else block runs if no exception is raised during the try block. It can be used to execute code that should only run if the try block succeeds.

try:
    num = int(input("Enter a number: "))
    result = 10 / num
except ZeroDivisionError:
    print("Cannot divide by zero.")
except ValueError:
    print("Invalid input. Please enter a valid number.")
else:
    print(f"The result is {result}")

In this example:

  • If the user enters a valid number and doesn’t cause an exception, the else block will execute and print the result.
  • If there’s an error, the corresponding except block will handle it.

7. The finally Block

The finally block is used to execute code that should run no matter what, regardless of whether an exception occurred or not. It's often used to perform clean-up actions, such as closing files or releasing resources.

try:
    file = open("example.txt", "r")
    content = file.read()
except FileNotFoundError as e:
    print("File not found!")
finally:
    file.close()  # This will always run, even if the exception is raised
    print("File closed.")

In this example:

  • If the file is successfully opened and read, the finally block will close the file.
  • If an exception occurs (e.g., the file doesn’t exist), the finally block will still close the file (if opened) and print "File closed."

8. Raising Exceptions

In some cases, you might want to raise exceptions deliberately in your code. This is done using the raise keyword.

def check_age(age):
    if age < 18:
        raise ValueError("Age must be at least 18")
    return "You are old enough."

try:
    print(check_age(16))
except ValueError as e:
    print(f"Error: {e}")

In this example:

  • The raise statement is used to raise a ValueError if the age is less than 18.
  • The exception is caught in the except block, and an error message is printed.

9. Custom Exceptions

You can create custom exceptions by defining a new class that inherits from the base Exception class.

class CustomError(Exception):
    pass

try:
    raise CustomError("This is a custom error.")
except CustomError as e:
    print(f"Caught an exception: {e}")

This allows you to define specialized exceptions for specific error conditions in your program.

10. Summary

  • Exceptions are used to handle errors in Python, allowing you to write code that can recover from unexpected situations.
  • try, except blocks are used to handle exceptions, while else and finally provide additional control over the execution flow.
  • Python provides a variety of built-in exceptions, and you can also define custom exceptions using the raise keyword.
  • Understanding and using exceptions properly helps in writing more robust and error-resistant code.

Commenting is not enabled on this course.