How to Check If an Exception Is of a Certain Type in Python

PythonPythonBeginner
Practice Now

Introduction

In this lab, you will learn how to check if an exception is of a certain type in Python, a crucial skill for effective error handling. The lab focuses on understanding the exception hierarchy and utilizing this knowledge to identify specific exception types.

The lab guides you through exploring the Python exception hierarchy, starting with the base class BaseException and its subclasses like Exception. You'll create a Python script, exception_hierarchy.py, to print the exception hierarchy, allowing you to visualize the relationships between different exception classes. This understanding will then be applied in subsequent steps to check exception types using isinstance() and direct class comparisons.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/ErrorandExceptionHandlingGroup -.-> python/raising_exceptions("Raising Exceptions") python/ErrorandExceptionHandlingGroup -.-> python/custom_exceptions("Custom Exceptions") subgraph Lab Skills python/catching_exceptions -.-> lab-559609{{"How to Check If an Exception Is of a Certain Type in Python"}} python/raising_exceptions -.-> lab-559609{{"How to Check If an Exception Is of a Certain Type in Python"}} python/custom_exceptions -.-> lab-559609{{"How to Check If an Exception Is of a Certain Type in Python"}} end

Understand Exception Hierarchy

In this step, you will learn about the exception hierarchy in Python. Understanding this hierarchy is crucial for effective error handling. Exceptions in Python are organized in a tree-like structure, with a base class at the top and more specific exception classes inheriting from it.

The base class for all exceptions is BaseException. Directly inheriting from BaseException are Exception, GeneratorExit, KeyboardInterrupt, and SystemExit. The Exception class is the superclass for most built-in exceptions that indicate errors your program might encounter.

Let's create a Python script to explore this hierarchy.

  1. Open your VS Code editor.

  2. Create a new file named exception_hierarchy.py in the ~/project directory.

    ~/project/exception_hierarchy.py
  3. Add the following code to the exception_hierarchy.py file:

    def print_exception_hierarchy(exception_class, indent=0):
        """Prints the exception hierarchy starting from a given exception class."""
        print('  ' * indent + str(exception_class))
        for subclass in exception_class.__subclasses__():
            print_exception_hierarchy(subclass, indent + 1)
    
    print("Exception Hierarchy:")
    print_exception_hierarchy(Exception)

    This script defines a recursive function print_exception_hierarchy that prints the exception hierarchy starting from the Exception class.

  4. Run the script using the following command in the terminal:

    python exception_hierarchy.py

    This will print a tree-like structure of the exception hierarchy to the terminal.

    Example output:

    Exception Hierarchy:
    <class 'Exception'>
      <class 'ArithmeticError'>
        <class 'FloatingPointError'>
        <class 'OverflowError'>
        <class 'ZeroDivisionError'>
          <class 'decimal.DivisionByZero'>
      <class 'AssertionError'>
      <class 'AttributeError'>
      <class 'BufferError'>
      <class 'EOFError'>
      <class 'ImportError'>
        <class 'ModuleNotFoundError'>
        <class 'ZipImportError'>
      <class 'LookupError'>
        <class 'IndexError'>
        <class 'KeyError'>
          <class 'tracemalloc.DomainKey'>
      <class 'MemoryError'>
      <class 'NameError'>
        <class 'UnboundLocalError'>
      <class 'OSError'>
        <class 'BlockingIOError'>
        <class 'ChildProcessError'>
        <class 'ConnectionError'>
          <class 'BrokenPipeError'>
          <class 'ConnectionAbortedError'>
          <class 'ConnectionRefusedError'>
          <class 'ConnectionResetError'>
        <class 'FileExistsError'>
        <class 'FileNotFoundError'>
        <class 'InterruptedError'>
          <class 'InterruptedSystemCall'>
        <class 'IsADirectoryError'>
        <class 'NotADirectoryError'>
        <class 'PermissionError'>
        <class 'ProcessLookupError'>
        <class 'TimeoutError'>
        <class 'UnsupportedOperation'>
        <class 'itertools.Incomplete'>
        <class 'signal.ItimerError'>
      <class 'ReferenceError'>
      <class 'RuntimeError'>
        <class 'NotImplementedError'>
          <class 'asyncio.exceptions.IncompleteReadError'>
          <class 'zlib.error'>
        <class '_frozen_importlib._DeadlockError'>
        <class 'RecursionError'>
      <class 'StopAsyncIteration'>
      <class 'StopIteration'>
      <class 'SyntaxError'>
        <class 'IndentationError'>
          <class 'TabError'>
      <class 'SystemError'>
      <class 'TypeError'>
      <class 'ValueError'>
        <class 'UnicodeError'>
          <class 'UnicodeDecodeError'>
          <class 'UnicodeEncodeError'>
          <class 'UnicodeTranslateError'>
      <class 'Warning'>
        <class 'BytesWarning'>
        <class 'DeprecationWarning'>
        <class 'EncodingWarning'>
        <class 'FutureWarning'>
        <class 'ImportWarning'>
        <class 'PendingDeprecationWarning'>
        <class 'ResourceWarning'>
        <class 'RuntimeWarning'>
        <class 'SyntaxWarning'>
        <class 'UnicodeWarning'>
        <class 'UserWarning'>

    This output shows the hierarchy of exceptions, with Exception as the base class and various subclasses representing specific types of errors. Understanding this hierarchy helps you catch exceptions at the appropriate level of granularity. For example, you can catch a specific exception like ZeroDivisionError or a more general exception like ArithmeticError (which is a parent of ZeroDivisionError).

Use isinstance() on Exceptions

In this step, you will learn how to use the isinstance() function to check if an exception is an instance of a particular class or a tuple of classes. This is useful for handling different types of exceptions in a flexible way.

The isinstance() function takes two arguments: an object and a classinfo. It returns True if the object is an instance of the classinfo, or of a subclass thereof. It returns False otherwise.

Let's create a Python script to demonstrate the use of isinstance() with exceptions.

  1. Open your VS Code editor.

  2. Create a new file named isinstance_exception.py in the ~/project directory.

    ~/project/isinstance_exception.py
  3. Add the following code to the isinstance_exception.py file:

    try:
        result = 10 / 0
    except Exception as e:
        if isinstance(e, ZeroDivisionError):
            print("Caught a ZeroDivisionError!")
        elif isinstance(e, ArithmeticError):
            print("Caught an ArithmeticError!")
        else:
            print("Caught some other exception!")
    
    print("Program continues...")

    In this script, we are trying to divide 10 by 0, which will raise a ZeroDivisionError. We then catch the exception and use isinstance() to check if it is an instance of ZeroDivisionError or ArithmeticError.

  4. Run the script using the following command in the terminal:

    python isinstance_exception.py

    This will print "Caught a ZeroDivisionError!" to the terminal.

    Example output:

    Caught a ZeroDivisionError!
    Program continues...

    The output shows that the isinstance() function correctly identified the exception as an instance of ZeroDivisionError. Because ZeroDivisionError is a subclass of ArithmeticError, the first if condition is met, and the corresponding message is printed.

    Now, let's modify the script to catch a more general exception.

  5. Modify the isinstance_exception.py file to the following:

    try:
        result = int("abc")
    except Exception as e:
        if isinstance(e, ZeroDivisionError):
            print("Caught a ZeroDivisionError!")
        elif isinstance(e, ValueError):
            print("Caught a ValueError!")
        elif isinstance(e, ArithmeticError):
            print("Caught an ArithmeticError!")
        else:
            print("Caught some other exception!")
    
    print("Program continues...")

    In this modified script, we are trying to convert the string "abc" to an integer, which will raise a ValueError.

  6. Run the script again using the same command:

    python isinstance_exception.py

    This will print "Caught a ValueError!" to the terminal.

    Example output:

    Caught a ValueError!
    Program continues...

    This output shows that isinstance() can be used to differentiate between different types of exceptions and handle them accordingly.

Check with Exception Classes

In this step, you will learn how to check for specific exception classes directly in your except blocks. This is a more direct and often clearer way to handle exceptions compared to using isinstance().

When you use except ExceptionType as e:, you are telling Python to catch only exceptions that are of the type ExceptionType or a subclass of it.

Let's create a Python script to demonstrate this.

  1. Open your VS Code editor.

  2. Create a new file named exception_classes.py in the ~/project directory.

    ~/project/exception_classes.py
  3. Add the following code to the exception_classes.py file:

    try:
        result = 10 / 0
    except ZeroDivisionError as e:
        print("Caught a ZeroDivisionError:", e)
    except ArithmeticError as e:
        print("Caught an ArithmeticError:", e)
    except Exception as e:
        print("Caught some other exception:", e)
    
    print("Program continues...")

    In this script, we are trying to divide 10 by 0, which will raise a ZeroDivisionError. We have three except blocks: one for ZeroDivisionError, one for ArithmeticError, and one for Exception.

  4. Run the script using the following command in the terminal:

    python exception_classes.py

    This will print "Caught a ZeroDivisionError: division by zero" to the terminal.

    Example output:

    Caught a ZeroDivisionError: division by zero
    Program continues...

    The output shows that the ZeroDivisionError was caught by the first except block.

    Now, let's modify the script to raise a different exception.

  5. Modify the exception_classes.py file to the following:

    try:
        result = int("abc")
    except ZeroDivisionError as e:
        print("Caught a ZeroDivisionError:", e)
    except ValueError as e:
        print("Caught a ValueError:", e)
    except ArithmeticError as e:
        print("Caught an ArithmeticError:", e)
    except Exception as e:
        print("Caught some other exception:", e)
    
    print("Program continues...")

    In this modified script, we are trying to convert the string "abc" to an integer, which will raise a ValueError.

  6. Run the script again using the same command:

    python exception_classes.py

    This will print "Caught a ValueError: invalid literal for int() with base 10: 'abc'" to the terminal.

    Example output:

    Caught a ValueError: invalid literal for int() with base 10: 'abc'
    Program continues...

    This output shows that the ValueError was caught by the second except block.

    By specifying the exception class directly in the except block, you can handle different types of exceptions in a clear and organized manner. This approach is generally preferred over using isinstance() for simple exception handling.

Summary

In this lab, you explored the exception hierarchy in Python, which is crucial for effective error handling. You learned that exceptions are organized in a tree-like structure with BaseException as the base class and Exception as the superclass for most built-in exceptions.

You created a Python script, exception_hierarchy.py, to print the exception hierarchy starting from the Exception class. By running the script, you observed the tree-like structure of exceptions and their relationships, gaining a better understanding of how exceptions are organized in Python.