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.
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.
Open your VS Code editor.
Create a new file named
exception_hierarchy.pyin the~/projectdirectory.~/project/exception_hierarchy.pyAdd the following code to the
exception_hierarchy.pyfile: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_hierarchythat prints the exception hierarchy starting from theExceptionclass.Run the script using the following command in the terminal:
python exception_hierarchy.pyThis 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
Exceptionas 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 likeZeroDivisionErroror a more general exception likeArithmeticError(which is a parent ofZeroDivisionError).
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.
Open your VS Code editor.
Create a new file named
isinstance_exception.pyin the~/projectdirectory.~/project/isinstance_exception.pyAdd the following code to the
isinstance_exception.pyfile: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 useisinstance()to check if it is an instance ofZeroDivisionErrororArithmeticError.Run the script using the following command in the terminal:
python isinstance_exception.pyThis 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 ofZeroDivisionError. BecauseZeroDivisionErroris a subclass ofArithmeticError, the firstifcondition is met, and the corresponding message is printed.Now, let's modify the script to catch a more general exception.
Modify the
isinstance_exception.pyfile 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.Run the script again using the same command:
python isinstance_exception.pyThis 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.
Open your VS Code editor.
Create a new file named
exception_classes.pyin the~/projectdirectory.~/project/exception_classes.pyAdd the following code to the
exception_classes.pyfile: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 threeexceptblocks: one forZeroDivisionError, one forArithmeticError, and one forException.Run the script using the following command in the terminal:
python exception_classes.pyThis 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
ZeroDivisionErrorwas caught by the firstexceptblock.Now, let's modify the script to raise a different exception.
Modify the
exception_classes.pyfile 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.Run the script again using the same command:
python exception_classes.pyThis 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
ValueErrorwas caught by the secondexceptblock.By specifying the exception class directly in the
exceptblock, you can handle different types of exceptions in a clear and organized manner. This approach is generally preferred over usingisinstance()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.



