Python tutorials > Error Handling > Exceptions > What are built-in exceptions?

What are built-in exceptions?

Python provides a rich set of built-in exceptions to handle various error conditions that can occur during program execution. These exceptions are pre-defined classes that inherit from the base Exception class. Understanding these exceptions is crucial for writing robust and reliable Python code.

This tutorial will guide you through some of the most common built-in exceptions, explaining their purpose and providing examples of how they can be raised and handled.

Introduction to Built-in Exceptions

Built-in exceptions are errors that are pre-defined in Python. They represent common problems encountered during program execution, such as attempting to divide by zero, accessing an undefined variable, or importing a non-existent module.

When an exception occurs (is 'raised'), the normal flow of the program is interrupted. If the exception is not 'caught' and handled using a try-except block, the program will terminate and print an error message (a traceback).

Common Built-in Exceptions

Here's a list of some of the most frequently encountered built-in exceptions in Python, along with a brief explanation:

  • ArithmeticError: Base class for arithmetic related errors.
  • ZeroDivisionError: Raised when division or modulo by zero occurs.
  • IndexError: Raised when a sequence subscript is out of range.
  • KeyError: Raised when a dictionary key is not found.
  • NameError: Raised when a local or global name is not found.
  • TypeError: Raised when an operation or function is applied to an object of inappropriate type.
  • ValueError: Raised when a function receives an argument of the correct type but an inappropriate value.
  • IOError: (Python 2) Raised when an I/O operation (e.g., opening a file) fails. Replaced by OSError in Python 3.
  • OSError: Raised when a system operation causes a system-related error.
  • ImportError: Raised when an import statement fails to find the module definition.
  • AttributeError: Raised when an attribute reference or assignment fails.
  • FileNotFoundError: (Python 3) Raised when a file or directory is requested but doesn’t exist.

ZeroDivisionError: Dividing by Zero

The ZeroDivisionError is raised when you attempt to divide a number by zero. The try-except block is used to catch this exception and handle it gracefully.

try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"Error: {e}")  # Output: Error: division by zero

IndexError: Accessing Out-of-Bounds Index

The IndexError occurs when you try to access an element in a sequence (like a list or tuple) using an index that is outside the valid range of indices.

my_list = [1, 2, 3]

try:
    print(my_list[3]) #index out of range
except IndexError as e:
    print(f"Error: {e}")  # Output: Error: list index out of range

KeyError: Accessing Non-Existent Key in Dictionary

The KeyError is raised when you try to access a dictionary using a key that does not exist in the dictionary.

my_dict = {'a': 1, 'b': 2}

try:
    print(my_dict['c'])
except KeyError as e:
    print(f"Error: {e}")  # Output: Error: 'c'

NameError: Using Undefined Variable

The NameError occurs when you try to use a variable that has not been assigned a value.

try:
    print(undefined_variable)
except NameError as e:
    print(f"Error: {e}")  # Output: Error: name 'undefined_variable' is not defined

TypeError: Incorrect Data Type

The TypeError is raised when you perform an operation or call a function with an argument of an inappropriate data type.

try:
    result = '5' + 5
except TypeError as e:
    print(f"Error: {e}")  # Output: Error: can only concatenate str (not "int") to str

ValueError: Invalid Value for Data Type

The ValueError is raised when a function receives an argument of the correct data type, but with an invalid value.

try:
    number = int('abc')
except ValueError as e:
    print(f"Error: {e}")  # Output: Error: invalid literal for int() with base 10: 'abc'

FileNotFoundError (or IOError): Attempting to Open a Non-Existent File

The FileNotFoundError (or IOError in older Python versions) is raised when you try to open a file that does not exist.

try:
    with open('non_existent_file.txt', 'r') as f:
        content = f.read()
except FileNotFoundError as e:
    print(f"Error: {e}")  # Output: Error: [Errno 2] No such file or directory: 'non_existent_file.txt'

Best Practices

  • Be Specific: Catch specific exceptions instead of using a broad except Exception:. This allows you to handle different error conditions in different ways and prevents masking unexpected errors.
  • Log Errors: Use the logging module to record information about exceptions, including the traceback. This helps with debugging and monitoring your application.
  • Raise Exceptions: Don't be afraid to raise your own exceptions when necessary. This can help to make your code more modular and easier to understand.
  • Clean Up Resources: Use try...finally blocks to ensure that resources (like files or network connections) are properly cleaned up, even if an exception occurs. Or, better yet, use context managers (with statement) which automatically handle resource cleanup.

When to Use Them

Use built-in exceptions when you want to signal an error condition that is already well-defined in Python. Using existing exceptions makes your code more readable and easier to understand for other Python developers. For situations where the built-in exceptions don't adequately represent the error, you should create custom exception classes.

Interview Tip

When discussing error handling in Python interviews, be sure to emphasize the importance of try-except blocks, the benefits of catching specific exceptions, and the proper use of finally (or context managers) for resource management. Understanding the hierarchy of exceptions (that all built-in exceptions inherit from BaseException) is also valuable.

FAQ

  • What is the base class for all built-in exceptions?

    All built-in exceptions inherit from the BaseException class. Exception is a direct subclass of BaseException and it is the class from which most exceptions that applications should handle are derived.
  • Should I catch all exceptions with a single except Exception: block?

    No, it's generally best practice to catch specific exceptions. Catching all exceptions can mask unexpected errors and make debugging more difficult.
  • How can I handle multiple exceptions in a single try-except block?

    You can use multiple except clauses, each handling a different exception type. You can also catch multiple exceptions in a single except clause using a tuple of exception types: except (TypeError, ValueError):