Intensity Coding
  • HOME
  • TUTORIALS
    • Python
    • Natural Language Processing
    • Generative AI
  • ABOUT US
    • About Us
    • Contact Us
    • Privacy Policy
    • Terms and Conditions
    • Disclaimer

Python

Python Exception Handling

Python
Python
  • Introduction To Python
  • Write Your First Python Program
  • Indentation And Comments in Python
  • Variables in Python
  • Data Types in Python
  • Booleans and Number in Python
  • Operators in Python
  • Mutable Vs Immutable Objects And Collection in Python
  • Python String
  • Python Lists
  • Python Tuples
  • Python Sets
  • Python Dictionaries
  • Python Control Statements
  • Python Functions
  • Python Lambda Functions
  • Python Exception Handling
  • Python File Handling
  • Python Modules
  • Python Package and PIP
  • Python Keywords
  • Python Built In Functions
  • Introduction To Object Oriented Programming Python
  • Python Classes and Objects
  • Python Inheritance
  • Python Encapsulation
  • Python Regular Expressions (RegEx)
  • Python JSON
  • Python Datetime

What are Errors?¶

  • When running a Python program, errors can occur due to:

    • Typographical or syntactic mistakes (e.g., missing colons, parentheses)
    • Invalid operations during execution (e.g., dividing by zero, accessing undefined variables)
  • Python categorizes errors into two major types:

Type Description Example
Syntax Errors(Parsing error) Detected by the Python parser before code execution. Missing colon in if x == 1 print(x)
Exceptions Detected during program execution. Dividing by zero or accessing a missing variable

Syntax Errors¶

  • A syntax error (or parsing error) occurs when Python fails to interpret your code because it violates grammatical rules.

  • When the parser encounters a syntax error, it stops execution immediately and displays an error message without running any part of the program.

  • Typical Python syntax errors include:

    • Improper or inconsistent indentation
    • Missing punctuation such as colons, commas, or brackets
    • Misplacement or incorrect use of reserved keywords
In [ ]:
# Missing colon at the end of 'while True'
while True print('Intensity Coding')
  File "/tmp/ipython-input-672742266.py", line 2
    while True print('Intensity Coding')
               ^
SyntaxError: invalid syntax
  • The caret (^) points to the spot where Python noticed something wrong. Often, the real problem is a few characters before the marked position.

Exceptions¶

  • Even if your code is syntactically correct, runtime errors can still occur. These are known as exceptions or Logical error.
In [ ]:
# Common runtime errors
print(10 * (1/0))         # ZeroDivisionError
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
/tmp/ipython-input-2217227179.py in <cell line: 0>()
      1 # Common runtime errors
----> 2 print(10 * (1/0))         # ZeroDivisionError

ZeroDivisionError: division by zero
  • This line raises a ZeroDivisionError because dividing by zero is undefined.
  • Each exception has:
    • A type (e.g., ZeroDivisionError)
    • A message describing what went wrong
    • A traceback, which shows the chain of calls leading to the error
  • If such errors aren’t handled, Python will stop the execution immediately. That’s where try-except blocks come into play.

What is an Exception?¶

  • An exception is an unexpected event that occurs during the execution of a program, interrupting its normal flow.

  • When a Python program encounters a situation it cannot process (like dividing by zero or referencing an undefined variable), it raises an exception a special Python object that signals the presence of an error.

  • Instead of letting the program crash, Python provides structured ways to handle these errors gracefully using the try-except mechanism.

  • Exception handling prevents programs from crashing and allows custom error messages.

  • In Python, an exception is an object that inherits from the BaseException class and stores details about an error that occurs during program execution. Each exception object holds:

    • The type of error (name of the exception)
    • The program’s state at the moment the error occurred
    • A descriptive message explaining the cause of the error
  • Exceptions help identify and handle various types of runtime failures. In Python, exceptions can be raised within a try block and handled using an except block.

Default Behavior¶

  • If the raised exception is not handled, Python stops the program immediately and displays an error message.
  • This abrupt termination can be avoided by using exception handling mechanisms.

Key Components of Exception Handling¶

Keyword Purpose
try Defines a block of code where exceptions may occur.
except Defines what to do when an exception is raised in the try block.
else Runs only if no exceptions are raised in the try block.
finally Executes regardless of whether an exception occurred or not.

Handling Exceptions with try and except Block¶

  • Python provides the try statement to catch and handle exceptions gracefully.
  • Within a try block, you place code that might potentially fail.
  • If an error is detected during execution, Python checks for a matching except block to handle it.

Generic Exception Handling¶

  • Python allows you to create an except block without specifying a particular exception type. This is known as generic exception handling.

  • This block will catch any exception, making it useful as a fallback for unexpected errors.

  • Note: Overusing generic except: clauses is discouraged, as it hides the exact cause of the problem.

Syntax

try:
    # Code that may raise an exception
except:
    # Code to handle the error
else:
   # Code that runs if no exception occurs
finally:
    # Code that always executes (cleanup)

Example:

In [ ]:
try:
    # Code that might raise an exception
    risky_operation = 10 / 0
except:
    # This will catch any type of exception
    print("An unexpected error occurred!")
An unexpected error occurred!

Example with else and finally:

In [ ]:
try:
    # Code that might raise an exception
    risky_operation = 10 / 2
except:
    # This will catch any type of exception
    print("An unexpected error occurred!")
else:
    # Executes only if no exception occurs
    print("Operation completed successfully.")
finally:
    # Code that always executes
    print("Execution completed.")
Operation completed successfully.
Execution completed.
NOTE Using a bare except: is discouraged in production code, as it makes debugging difficult. Always prefer catching specific exceptions when possible.

Catching Specific Exceptions¶

  • Using a generic exception handler like except Exception: or except: might seem convenient, but it’s bad practice because:

    • It hides unexpected bugs.
    • It makes debugging difficult.
    • It may catch system-level exceptions unintentionally.
  • Instead of catching all exceptions, it is a good practice to handle specific exception types.

  • This approach makes your code more readable, debuggable, and robust.

  • For instance, if you’re working with file operations, catch only file-related errors like FileNotFoundError or IOError.

  • By specifying which exceptions to catch, you can customize how your program responds to each type of error.

Syntax

try:
    # Code that might cause an exception
except ExceptionType:
    # Code to handle the error
else:
    # Code to execute if no exception occurs
finally:
    # Code that always executes (cleanup)

Example:

In [ ]:
try:
    # Code that might raise an exception
    risky_operation = 10 / 0
except ZeroDivisionError:
    # Handle division by zero
    print("Error: Cannot divide by zero.")
Error: Cannot divide by zero.

Example with else and finally:

In [ ]:
try:
    # Code that might raise an exception
    risky_operation = 10 / 0
except ZeroDivisionError:
    # Handle division by zero
    print("Error: Cannot divide by zero.")
else:
    # Executes only if no exception occurs
    print("Operation completed successfully.")
finally:
    # Code that always executes
    print("Execution completed.")
Error: Cannot divide by zero.
Execution completed.

Handling Multiple Exceptions¶

  • A single try block can be followed by multiple except clauses, each tailored to handle a specific type of exception.

  • This is helpful when the code in the try block can raise different types of exceptions.

In [ ]:
def divide_numbers(a, b):
    try:
        # Try dividing two numbers
        result = a / b
        print("Result:", result)
    except ZeroDivisionError:
        # Handle division by zero
        print("Error: Cannot divide by zero.")
    except TypeError:
        # Handle invalid data types
        print("Error: Both inputs must be numbers.")
    except Exception:
        # Catch-all for any other unforeseen exceptions
        print("Unexpected Error:")

# Example calls
divide_numbers(10, 2)     # Expected output: Result: 5.0
divide_numbers(10, 0)     # Expected output: Error: Cannot divide by zero.
divide_numbers(10, 'a')   # Expected output: Error: Both inputs must be numbers.
Result: 5.0
Error: Cannot divide by zero.
Error: Both inputs must be numbers.

Explanation:

  • ZeroDivisionError handles the case when b is 0.
  • TypeError handles invalid input types (like dividing by a string).
  • The generic Exception block handles any other unforeseen exceptions.

Catching Multiple Specific Exceptions Together¶

  • You can handle multiple exception types in a single block by grouping them in parentheses:
 try:
    # Some risky operation
except (TypeError, ValueError):
    print("Caught either a TypeError or ValueError")
In [ ]:
try:
    num = int(input("Enter a number: "))
    print(10 / num)
except (ValueError, ZeroDivisionError) as e:
    print("Input error: ", e)
Enter a number: 0
Input error:  division by zero

How it works:

  • If the user enters a non-numeric value, a ValueError occurs.
  • If the user enters 0, a ZeroDivisionError occurs.
  • Both are caught by the same handler.

Using else Clause¶

  • An optional else block can be included after all except blocks.
  • The else block runs only when no exceptions are raised in the try block.
  • This is a good place for code that should only execute when the try block succeeds completely.
In [ ]:
try:
    print("Hello from Intensity Coding!")
except:
    print("An error occurred")
else:
    print("No exceptions occurred")

# Output:
# Hello from Intensity Coding!
# No exceptions occurred
Hello from Intensity Coding!
No exceptions occurred

Using finally Block¶

  • The finally block is always executed—no matter what happens in the try or except blocks.

  • It is commonly used for resource clean-up, such as closing files or releasing memory.

In [ ]:
try:
    print(z)
except:
    print("An error occurred")
finally:
    print("This block always runs")

# Output:
# An error occurred
# This block always runs
An error occurred
This block always runs

Intensity Coding.png

Capturing Exception Arguments¶

  • When handling exceptions in Python, it's often useful to access specific details about the error. This is done by capturing the exception object using the as keyword in the except clause.

  • By doing so, you gain access to the underlying message or cause of the exception, which helps in debugging and logging.

Single Exception Handling with Argument¶

Syntax

try:
    # Code that may raise an error
except ExceptionType as error_variable:
    # Use 'error_variable' to access the error details
In [ ]:
# Function to convert a value to an integer
def convert_to_integer(value):
    try:
        return int(value)
    except ValueError as error_info:
        print("Conversion failed. Reason:", error_info)

# Test the function with invalid input
convert_to_integer("intensity")

# Output:
# Conversion failed. Reason: invalid literal for int() with base 10: 'intensity'
Conversion failed. Reason: invalid literal for int() with base 10: 'intensity'

Handling Multiple Exceptions with a Shared Variable¶

try:
    # Code that may raise different types of exceptions
except (TypeError, ValueError) as error_variable:
    # 'error' captures whichever exception was raised
  • ExceptionType: The specific type of error you want to catch (e.g., ValueError, TypeError, etc.)

  • error_variable: A variable that stores the exception object.

  • This object contains:

    • The type of error (name of the exception)
    • The program’s state at the moment the error occurred
    • A descriptive message explaining the cause of the error
In [ ]:
try:
    num = int(input("Enter a number: "))
    print(10 / num)
except (ValueError, ZeroDivisionError) as e:
    print("Input error: ", e)
Enter a number: 0
Input error:  division by zero
  • In this example:
    • The e variable captures the actual error message raised from either ZeroDivisionError or ValueError.
    • This makes it easier to handle and log the root cause of issues without writing separate blocks for each.

Nested try Blocks¶

  • In Python, nested try blocks allow you to handle exceptions at multiple levels. A nested try block is simply a try block placed inside another try block. This structure is useful for separating error handling for different parts of your code, making it more robust and easier to debug.
In [ ]:
def divide_numbers(a,b):
    """
    Function to divide two numbers provided by the user.
    Handles invalid input and division by zero using nested try blocks.
    """
    try:
        # Outer try block: Handle input errors
        num1 = int(a)
        num2 = int(b)

        try:
            # Inner try block: Handle division errors
            result = num1 / num2
        except ZeroDivisionError:
            print("Error: Cannot divide by zero.")
        else:
            print("Division result is:", result)
        finally:
            print("Inner try block executed.")

    except ValueError:
        print("Error: Invalid input. Please enter integers only.")
    finally:
        print("Outer try block executed.")

# Call the function
divide_numbers(10,2)
print("----------")
divide_numbers(10,0)
print("----------")
divide_numbers(10,'a')
Division result is: 5.0
Inner try block executed.
Outer try block executed.
----------
Error: Cannot divide by zero.
Inner try block executed.
Outer try block executed.
----------
Error: Invalid input. Please enter integers only.
Outer try block executed.

Raising Exceptions Manually¶

  • While Python provides built-in exceptions (like ValueError, TypeError, etc.), you can raise exceptions manually to handle situations where you want the program to explicitly signal an error.

  • The raise keyword allows you to trigger an exception yourself:

raise ExceptionType("Error message")

Example 1: Raise a general exception¶

In [ ]:
x = -5
if x < 0:
    raise Exception("Negative numbers are not allowed in Intensity Coding!")

# Output:
# Exception: Negative numbers are not allowed in Intensity Coding!
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
/tmp/ipython-input-5-3440258374.py in <cell line: 0>()
      1 x = -5
      2 if x < 0:
----> 3     raise Exception("Negative numbers are not allowed in Intensity Coding!")
      4 
      5 # Output:

Exception: Negative numbers are not allowed in Intensity Coding!

Example 2: Raise a specific exception¶

In [ ]:
# Function to check age input
def check_age(age):
    if age < 0:
        raise ValueError("Age cannot be negative")
    else:
        return f"Age is {age}"

# Testing
print(check_age(25))  # Works fine
print(check_age(-5))  # Raises ValueError: Age cannot be negative
Age is 25
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipython-input-117348710.py in <cell line: 0>()
      8 # Testing
      9 print(check_age(25))  # Works fine
---> 10 print(check_age(-5))  # Raises ValueError: Age cannot be negative

/tmp/ipython-input-117348710.py in check_age(age)
      2 def check_age(age):
      3     if age < 0:
----> 4         raise ValueError("Age cannot be negative")
      5     else:
      6         return f"Age is {age}"

ValueError: Age cannot be negative

Exception Chaining¶

  • When handling errors in Python, sometimes one exception leads to another. For example, you might catch one error, handle it partially, but then raise a new one because the situation still can’t be resolved.
  • In such cases, Python allows you to chain exceptions — linking the original cause (the first exception) with the new one you raise later.
  • This concept is known as Exception Chaining.

Why Do We Need Exception Chaining?¶

  • Imagine this sequence:
  1. You attempt an operation (like opening a file).
  2. That operation fails (e.g., FileNotFoundError).
  3. You catch that exception and raise another one (e.g., RuntimeError) to give a higher-level message.
  • Without chaining, Python would forget the original cause of the error. With chaining, you preserve both:

    • The original exception (cause)
    • The new exception (effect)
  • This helps in debugging, as you see both what failed originally and why a new exception was raised afterward.

Syntax of Exception Chaining¶

  • Python supports two forms of chaining:

1. Implicit Exception Chaining¶

  • Occurs automatically when you raise a new exception inside an except block.
In [ ]:
try:
    1 / 0
except ZeroDivisionError:
    raise ValueError("Invalid mathematical operation")
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
/tmp/ipython-input-2729777627.py in <cell line: 0>()
      1 try:
----> 2     1 / 0
      3 except ZeroDivisionError:

ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
/tmp/ipython-input-2729777627.py in <cell line: 0>()
      2     1 / 0
      3 except ZeroDivisionError:
----> 4     raise ValueError("Invalid mathematical operation")

ValueError: Invalid mathematical operation

2. Explicit Exception Chaining with from¶

  • You can explicitly specify the cause of a new exception using the from keyword.
In [ ]:
try:
    num = int("abc")  # will raise ValueError
except ValueError as e:
    raise TypeError("Data type conversion failed") from e
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipython-input-3085465140.py in <cell line: 0>()
      1 try:
----> 2     num = int("abc")  # will raise ValueError
      3 except ValueError as e:

ValueError: invalid literal for int() with base 10: 'abc'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
/tmp/ipython-input-3085465140.py in <cell line: 0>()
      2     num = int("abc")  # will raise ValueError
      3 except ValueError as e:
----> 4     raise TypeError("Data type conversion failed") from e

TypeError: Data type conversion failed

Suppressing the Context¶

  • Sometimes you don’t want to show the original cause.
  • You can suppress the automatic chaining by raising with from None.
In [ ]:
try:
    1 / 0
except ZeroDivisionError:
    raise RuntimeError("Computation failed") from None
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/tmp/ipython-input-406400982.py in <cell line: 0>()
      2     1 / 0
      3 except ZeroDivisionError:
----> 4     raise RuntimeError("Computation failed") from None

RuntimeError: Computation failed

Assert Statement¶

  • An assert statement is a built-in debugging tool used to verify that a condition holds true while a program is running.

  • When the condition evaluates to True, the program continues normally. If the condition evaluates to False, Python raises an AssertionError, optionally showing a custom message.

  • Assertions are used for detecting logical mistakes early, preventing invalid data from flowing through the program and ensuring preconditions and postconditions of algorithms.

Syntax of an Assert Statement¶

Basic Form

assert condition

With a Custom Error Message

assert condition, "Error message"

Example: Validating Input Range¶

In [ ]:
# Example: Ensure a value lies within an expected range
x = 12

# Assert that x is less than 10
assert x < 10, "Value of x exceeded the allowed threshold"

# Expected: AssertionError (since 12 < 10 is False)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
/tmp/ipython-input-589683157.py in <cell line: 0>()
      3 
      4 # Assert that x is less than 10
----> 5 assert x < 10, "Value of x exceeded the allowed threshold"
      6 
      7 # Expected: AssertionError (since 12 < 10 is False)

AssertionError: Value of x exceeded the allowed threshold

When Not to Use Assertions¶

  • Assertions should not be used for user-facing error handling. They are mainly for internal checks during development.

The Exception Lifecycle¶

  • The lifecycle of an exception describes the journey from when the error occurs to when it is handled (or causes the program to terminate).
  • It typically includes five stages:

Stage 1: Exception Occurrence¶

  • When Python executes a line that leads to an error, an exception object is created automatically.

  • The type of exception depends on the nature of the error (e.g., ZeroDivisionError, ValueError, FileNotFoundError).

  • At this point, Python pauses execution and prepares to handle the error.
In [ ]:
# Stage 1: Exception occurrence
result = 10 / 0  # Raises ZeroDivisionError

Stage 2: Exception Propagation¶

  • If the exception is not handled where it occurs, Python propagates it up the call stack.
  • This means it checks if any calling function or block has a matching except handler.
In [ ]:
def divide(a, b):
    return a / b  # Exception occurs here

def main():
    divide(10, 0)  # Propagation to main()

main()  # If not handled, it will propagate to interpreter
  • If no handler is found at any level, the exception continues to bubble up to the top level (Python interpreter).

Stage 3: Exception Handling¶

  • If Python finds a matching except block for the raised exception, it executes that block.
  • Once handled, program control resumes after the except block.
In [ ]:
try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"Handled Exception: {e}")

print("Program continues...")
Handled Exception: division by zero
Program continues...

Stage 4: Exception Termination (Uncaught Exception)¶

  • If the exception is not handled anywhere in the call stack, Python terminates the program.

  • Before termination, Python prints the exception traceback, showing where the error occurred.

In [ ]:
def divide(a, b):
    return a / b  # Unhandled

divide(10, 0)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
/tmp/ipython-input-3535963310.py in <cell line: 0>()
      2     return a / b  # Unhandled
      3 
----> 4 divide(10, 0)

/tmp/ipython-input-3535963310.py in divide(a, b)
      1 def divide(a, b):
----> 2     return a / b  # Unhandled
      3 
      4 divide(10, 0)

ZeroDivisionError: division by zero

Stage 5: Cleanup Phase (Finally Block)¶

  • The finally block executes no matter what — whether the exception occurs or not.

  • It is used for releasing resources like files, database connections, etc.

In [ ]:
# Example
try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("File not found!")
finally:
    print("Closing resources...")
File not found!
Closing resources...

The Exception Lifecycle.png

Advantages of Exception Handling in Python¶

  • Improves Program Stability: Prevents unexpected crashes by catching errors and allowing controlled recovery.
  • Clearer Code Structure: Keeps normal logic separate from error-handling logic, reducing clutter.
  • Easier Debugging: Python tracebacks highlight where an exception occurred, speeding up diagnosis.
  • Better Resource Control: Ensures files, database connections, and network links are closed correctly.
  • Cleaner Flow Control: Reduces the need for multiple conditional checks by handling errors directly.

Disadvantages of Exception Handling in Python¶

  • Possible Overuse: Using exceptions when simple checks would suffice can complicate code.
  • Performance Cost: Raising and catching exceptions is slower than basic condition checks.
  • Hidden Bugs: Broad exception blocks may suppress real programming errors.
  • Higher Complexity: Managing many exception cases can make code harder to read.
  • Security Risks: Poorly managed exceptions may expose sensitive details through error messages.

Categories of Exceptions¶

  • Python broadly groups exceptions into two categories:

    1. User-Defined Exceptions
    2. Built-in Exceptions
  • Both types ultimately inherit from Python’s root exception class: BaseException

User-Defined Exceptions¶

  • In addition to using built-in exception types like ValueError or TypeError, Python allows you to define custom exception classes by extending existing exceptions such as Exception or RuntimeError.

  • This approach is especially useful when:

    • You want to handle application-specific errors in a clean and descriptive way.
    • You need to differentiate between different types of errors within your domain.
    • You wish to add context or custom attributes to the error.
  • A custom exception is created by defining a new class that derives from the built-in Exception class.

1. Basic Custom Exception¶

  • The simplest possible custom exception includes only a class definition:
In [ ]:
# Minimal custom exception
class CustomException(Exception):
    pass
  • This class doesn’t add new behavior yet, but it allows you to raise and catch a clearly named exception.

Raising the Exception

In [ ]:
raise CustomException("This is a custom exception")

# Expected Output:
# CustomException: This is a custom exception
---------------------------------------------------------------------------
CustomException                           Traceback (most recent call last)
/tmp/ipython-input-879847413.py in <cell line: 0>()
----> 1 raise CustomException("This is a custom exception")
      2 
      3 # Expected Output:
      4 # CustomException: This is a custom exception

CustomException: This is a custom exception

2. Adding Functionality to Custom Exceptions¶

  • In many applications, you need the exception to store additional details such as:

    • An error code
    • Metadata about the failure
    • A specific value related to the issue
  • To do this, override the constructor and store extra attributes

In [ ]:
# Custom exception with additional attributes
class CustomException(Exception):
    def __init__(self, message, error_code):
        # Pass the message to the base Exception class
        super().__init__(message)
        # Store metadata for programmatic handling
        self.error_code = error_code
  • This makes the exception more informative and useful during debugging or error logging.

Raising the Enhanced Exception

In [ ]:
raise CustomException("This is a custom exception", 404)

# Expected Output:
# CustomException: This is a custom exception
---------------------------------------------------------------------------
CustomException                           Traceback (most recent call last)
/tmp/ipython-input-3853781119.py in <cell line: 0>()
----> 1 raise CustomException("This is a custom exception", 404)
      2 
      3 # Expected Output:
      4 # CustomException: This is a custom exception

CustomException: This is a custom exception

Accessing Extra Attributes During Handling

In [ ]:
try:
    raise CustomException("Training failed due to invalid input", 501)
except CustomException as err:
    print("Message:", err)
    print("Error Code:", err.error_code)

# Expected Output:
# Message: Training failed due to invalid input
# Error Code: 501
Message: Training failed due to invalid input
Error Code: 501

Python Built-in Exceptions¶

  • Python includes a comprehensive set of built-in exception classes designed to capture common runtime errors.
  • These exceptions cover mathematical issues, lookup failures, file operations, system signals, and much more.
  • All built-in exceptions ultimately inherit from the root class BaseException.
  • This forms the foundation of Python’s exception model and ensures consistent behavior across all error types.

Exception hierarchy(Built-in)¶

  • Below is the structured hierarchy of Python’s main built-in exceptions. This layout shows how broader exception types group together specific error categories. Taken from the official Python documentation
BaseException
 ├── BaseExceptionGroup
 ├── GeneratorExit
 ├── KeyboardInterrupt
 ├── SystemExit
 └── Exception
      ├── ArithmeticError
      │    ├── FloatingPointError
      │    ├── OverflowError
      │    └── ZeroDivisionError
      ├── AssertionError
      ├── AttributeError
      ├── BufferError
      ├── EOFError
      ├── ExceptionGroup [BaseExceptionGroup]
      ├── ImportError
      │    └── ModuleNotFoundError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── MemoryError
      ├── NameError
      │    └── UnboundLocalError
      ├── OSError
      │    ├── BlockingIOError
      │    ├── ChildProcessError
      │    ├── ConnectionError
      │    │    ├── BrokenPipeError
      │    │    ├── ConnectionAbortedError
      │    │    ├── ConnectionRefusedError
      │    │    └── ConnectionResetError
      │    ├── FileExistsError
      │    ├── FileNotFoundError
      │    ├── InterruptedError
      │    ├── IsADirectoryError
      │    ├── NotADirectoryError
      │    ├── PermissionError
      │    ├── ProcessLookupError
      │    └── TimeoutError
      ├── ReferenceError
      ├── RuntimeError
      │    ├── NotImplementedError
      │    ├── PythonFinalizationError
      │    └── RecursionError
      ├── StopAsyncIteration
      ├── StopIteration
      ├── SyntaxError
      │    └── IndentationError
      │         └── TabError
      ├── SystemError
      ├── TypeError
      ├── ValueError
      │    └── UnicodeError
      │         ├── UnicodeDecodeError
      │         ├── UnicodeEncodeError
      │         └── UnicodeTranslateError
      └── Warning
           ├── BytesWarning
           ├── DeprecationWarning
           ├── EncodingWarning
           ├── FutureWarning
           ├── ImportWarning
           ├── PendingDeprecationWarning
           ├── ResourceWarning
           ├── RuntimeWarning
           ├── SyntaxWarning
           ├── UnicodeWarning
           └── UserWarning

Respecting Exception Hierarchy¶

  • When working with multiple except blocks, it is important to understand how Python decides which handler to execute.

  • Python checks each except clause in the order they appear, matching the first compatible exception type.

  • Because of this, the order of exception classes must follow the exception hierarchy correctly.

  • A general rule is:

    • Always place more specific exceptions first.
    • Place broader or base exceptions later.
    • Avoid catching the base Exception class unless there is a good reason, because it hides errors that should be handled explicitly.

Why Exception Order Matters¶

  • Python's exception mechanism stops the search once it finds the first matching handler. Since classes like ValueError, TypeError, and others inherit from the base Exception class, placing Exception too early will prevent more specific handlers from ever running.

Correct Ordering of Multiple Exceptions¶

In [ ]:
# Example : Proper exception ordering

try:
    # Code block that may cause various errors
    value = int("abc")        # Will raise ValueError
except ValueError:
    # Handles conversion errors
    print("Invalid conversion: a ValueError occurred.")
except Exception:
    # Fallback for unexpected exception types
    print("An unexpected exception occurred.")

# Expected Output:
# Invalid conversion: a ValueError occurred.
Invalid conversion: a ValueError occurred.
  • Here, ValueError is handled first. Any other exception type still derived from Exception will fall into the next block.

What Happens if the Base Exception Comes First?¶

  • If a broad exception class such as Exception is placed before specific handlers, Python will never reach those specific handlers. This leads to unreachable code.
In [ ]:
# Example  : Incorrect ordering (should be avoided)

try:
    x = 10 / 0               # Raises ZeroDivisionError
except Exception as e:
    print(f"General handler: {e}")  # This executes first
except ZeroDivisionError:
    print("You will never see this message.")
except ValueError:
    print("This is also unreachable.")

# Expected Output:
# General handler: division by zero
General handler: division by zero
  • Because Exception catches everything, the two specific handlers below it will never execute.

Understand Built-in Exceptions¶

No. Exception Name Description
1 BaseException Root class for all built-in exceptions and used for catching all exceptions in generic scenarios.
2 BaseExceptionGroup Represents a group of exceptions raised together (Python 3.11+).
3 GeneratorExit Raised automatically when a generator’s close() method is called.
4 KeyboardInterrupt Triggered when the user interrupts execution manually (e.g., Ctrl+C, Ctrl+Z).
5 SystemExit Raised when the sys.exit() function is called to stop the interpreter.
6 Exception Base class for most common runtime exceptions.
7 ArithmeticError Base class for numeric and arithmetic issues. Indicates issues in arithmetic or numeric operations (e.g., overflow, division errors).
8 FloatingPointError Floating-point computation error (rare).
9 OverflowError Occurs when a numeric operation exceeds the limits of the number type.
10 ZeroDivisionError Raised when dividing by zero using / or //.
11 AssertionError Triggered when an assert statement condition evaluates to false.
12 AttributeError Raised when an invalid or missing attribute is accessed on an object.
13 BufferError Issues related to buffer operations.
14 EOFError Occurs when input() reaches an unexpected end-of-file (EOF) without reading data.
15 ExceptionGroup Groups multiple Exception objects (Python 3.11+).
16 ImportError Indicates failure when trying to import a module that doesn't exist or fails to load.
17 ModuleNotFoundError Specific case when a module cannot be located.
18 LookupError The base class for lookup-related errors like IndexError and KeyError.
19 IndexError Occurs when trying to access a sequence (like list or string) using an invalid index.
20 KeyError Raised when a non-existent key is accessed in a dictionary.
21 MemoryError Raised when Python runs out of memory during execution.
22 NameError Indicates that a variable or identifier is not defined.
23 UnboundLocalError Raised when a local variable is accessed before it has been assigned a value.
24 OSError Base class for OS related failures.
25 BlockingIOError Raised when non-blocking operation would block.
26 ChildProcessError Failure related to child process operations occurs.
27 ConnectionError Base class for network/connection failures.
28 BrokenPipeError Raised when writing to closed pipe/socket.
29 ConnectionAbortedError Raised when connection aborted by the peer.
30 ConnectionRefusedError Raised when connection attempt refused by server.
31 ConnectionResetError Raised when connection reset by peer.
32 FileExistsError Raised when attempt to create file/dir that already exists.
33 FileNotFoundError Raised when file or directory does not exist.
34 InterruptedError Raised when system call interrupted by a signal.
35 IsADirectoryError Raised when expected a file but found a directory.
36 NotADirectoryError Raised when path component expected to be directory but was not.
37 PermissionError Raised when insufficient permissions for operation.
38 ProcessLookupError Raised when process does not exist.
39 TimeoutError Raised when operation times out.
40 ReferenceError Raised when weak reference refers to a deleted object.
41 RuntimeError General runtime error not fitting other categories.
42 NotImplementedError Occurs when an abstract method requires an inherited class to override the method
43 PythonFinalizationError Error occurring during interpreter shutdown.
44 RecursionError Raised when maximum recursion depth exceeded.
45 StopAsyncIteration Raised when end of asynchronous iterator.
46 StopIteration Raised by next() when there are no more items in an iterator.
47 SyntaxError Raised when the Python interpreter detects incorrect syntax.
48 IndentationError Raised due to incorrect or inconsistent indentation in the code.
49 TabError Occurs when indentation consists of tabs or spaces
50 SystemError Raised when the interpreter encounters an system error (not user-related).
51 TypeError Raised when you try to use two values of different or unsupported data types together.
52 ValueError Occurs when there is a incorrect value in a specified data type
53 UnicodeError Base for Unicode encoding/decoding issues.
54 UnicodeDecodeError Raised when decoding a byte stream into Unicode fails.
55 UnicodeEncodeError Raised during errors in converting Unicode to a specific encoding format.
56 UnicodeTranslateError Occurs when a Unicode translation process fails.

Some Example of Built-in Exceptions¶

BaseException¶

  • The root of all exceptions in Python. Rarely used directly; usually used for catching all exceptions in generic scenarios.
In [10]:
try:
    raise BaseException("This is a base exception")
except BaseException as e:
    print(f"Caught exception: {e}")
# Output: Caught exception: This is a base exception
Caught exception: This is a base exception

KeyboardInterrupt¶

  • A KeyboardInterrupt is raised when a running Python program is manually stopped by the user.

  • This usually happens when someone presses Ctrl + C in the terminal, which sends an interrupt signal telling the program to halt immediately.

  • This exception commonly appears in two situations:

    1. When a program is stuck in a long-running or infinite loop.
    2. When Python is waiting for user input through input() or similar operations.

Example 1: Interrupting an Infinite Loop

In [ ]:
# Handling KeyboardInterrupt in an Infinite Loop

try:
    while True:
        pass
except KeyboardInterrupt:
    print("Program interrupted by the user.")
Program interrupted by the user.
  • When the user presses Ctrl + C, Python terminates the loop and triggers the KeyboardInterrupt exception, which is handled by the except block.

Example 2: Interrupting During User Input

  • KeyboardInterrupt can also be triggered when Python is waiting for input.
In [ ]:
# Handling KeyboardInterrupt During Input
try:
    name = input("Please enter your name: ")
    print(f"Hello, {name}! Welcome to Intensity Coding.")
except KeyboardInterrupt:
    print("Input cancelled. Exiting program safely.")
Input cancelled. Exiting program safely.

What Happens Here?

  • Python waits at the input() line.
  • If the user presses Ctrl + C instead of typing a name, a KeyboardInterrupt is raised.
  • The except block catches the interruption and prints a clean exit message.

Exception¶

  • Most exceptions inherit from this class. Exception serves as the base class for nearly all common errors.
  • When you catch Exception, you are essentially handling a wide range of runtime issues such as type errors, value errors, indexing mistakes, and more.
  • It is often used when you want to catch any non-fatal exception without specifying a particular error type
In [9]:
# Demonstrating the Base Exception Class
try:
    # Attempting an invalid numeric conversion triggers a ValueError,
    # but here we catch it using the general Exception class.
    result = int("not_a_number")
except Exception as err:
    print(f"General Exception Caught: {err}")

# Expected Output:
# General Exception Caught: invalid literal for int() with base 10: 'not_a_number'
General Exception Caught: invalid literal for int() with base 10: 'not_a_number'

Explanation

  • Converting a non-numeric string to an integer raises a ValueError.
  • Because ValueError is a subclass of Exception, the generic except block handles it.
  • This is helpful when you want broad protection but should be used carefully to avoid masking specific errors.

OverflowError¶

  • Raised when a numeric calculation exceeds the maximum limit that Python can handle.
  • Commonly occurs with floating-point operations or very large exponentials.
  • Mostly seen in math functions like math.exp() for huge numbers.
In [11]:
import math
try:
    # Attempt to calculate exponential of a very large number
    result = math.exp(1000)  # Exceeds floating-point limits
except OverflowError as e:
    print("Caught OverflowError:", e)
Caught OverflowError: math range error

ZeroDivisionError¶

  • A ZeroDivisionError occurs when a number is divided by zero. In mathematics, division by zero is undefined.
  • Python enforces this rule and raises an exception instead of producing an unpredictable output.
In [12]:
# ZeroDivisionError Demonstration
try:
    value = 12 / 0
except ZeroDivisionError as err:
    print(f"Caught ZeroDivisionError: {err}")
Caught ZeroDivisionError: division by zero

AssertionError¶

  • An AssertionError occurs when an assert statement evaluates to False.

  • Assertions act as internal checkpoints that verify assumptions made while writing code.

  • They are useful for:

    • Validating intermediate results
    • Catching logical mistakes early
    • Ensuring conditions remain true during execution
    • Making debugging easier
  • Assertions should not be used for handling user-facing errors. They are primarily for developers to verify correct program behavior.

Syntex

assert <condition>, <optional message>
In [6]:
x = 3
try:
    assert x > 10, "x must be greater than 10"
except AssertionError as e:
    print(e)
# Output: x must be greater than 10
x must be greater than 10

AttributeError¶

  • Raised when an object does not have the attribute or method you are trying to access.
  • Commonly occurs when calling a non-existent method or accessing a wrong property of an object.
In [13]:
try:
    my_list = [1, 2, 3]
    # Attempt to call a non-existent method
    my_list.push(4)  # Lists have append(), not push()
except AttributeError as e:
    print("Caught AttributeError:", e)
Caught AttributeError: 'list' object has no attribute 'push'

ImportError¶

  • Raised when importing a module or object fails, often because the module exists but the specific object doesn’t.
In [3]:
try:
    # Attempt to import a function that does not exist in math
    from math import unknown_function
except ImportError as e:
    print("Caught ImportError:", e)
Caught ImportError: cannot import name 'unknown_function' from 'math' (unknown location)

ModuleNotFoundError¶

  • Raised when trying to import a module that does not exist.
In [4]:
try:
    # Attempt to import a module that is not installed
    import some_nonexistent_module
except ModuleNotFoundError as e:
    print("Caught ModuleNotFoundError:", e)
Caught ModuleNotFoundError: No module named 'some_nonexistent_module'

IndexError¶

  • Raised when trying to access an element using an invalid index in a sequence (like a list, tuple, or string).
In [2]:
try:
    my_list = [10, 20, 30]
    print(my_list[5])  # Index 5 does not exist
except IndexError as e:
    print("Caught IndexError:", e)
Caught IndexError: list index out of range

KeyError¶

  • Raised when trying to access a dictionary key that does not exist.
In [1]:
try:
    my_dict = {"a": 1, "b": 2}
    print(my_dict["c"])  # Key 'c' does not exist
except KeyError as e:
    print("Caught KeyError:", e)
Caught KeyError: 'c'

NameError¶

  • Raised when a variable or function name is not defined in the current scope.
In [36]:
try:
    # Attempting to use a variable that does not exist
    print(my_variable)
except NameError as e:
    print("Caught NameError:", e)
Caught NameError: name 'my_variable' is not defined

UnboundLocalError¶

  • Raised when a local variable is accessed before it has been assigned a value.
In [35]:
try:
    def calculate():
        # Trying to use x before assigning
        print(x)
        x = 10
    calculate()
except UnboundLocalError as e:
    print("Caught UnboundLocalError:", e)
Caught UnboundLocalError: cannot access local variable 'x' where it is not associated with a value

FileExistsError¶

  • Raised when an operation tries to create a file or directory that already exists.
In [34]:
import os

try:
    # Attempt to create a directory that already exists
    os.mkdir("my_folder")  # First time: creates successfully
    os.mkdir("my_folder")  # Second time: raises FileExistsError
except FileExistsError as e:
    print("Caught FileExistsError:", e)
Caught FileExistsError: [Errno 17] File exists: 'my_folder'

FileNotFoundError¶

  • Raised when an operation tries to access a file or directory that does not exist
In [32]:
try:
    # Attempt to open a file that does not exist
    with open("nonexistent_file.txt", "r") as f:
        content = f.read()
except FileNotFoundError as e:
    print("Caught FileNotFoundError:", e)
Caught FileNotFoundError: [Errno 2] No such file or directory: 'nonexistent_file.txt'

IsADirectoryError¶

  • Raised when a file operation expects a file, but the path points to a directory instead.
  • Commonly occurs when trying to open a directory as a file.
In [31]:
try:
    # Suppose "my_folder" is an existing directory
    with open("my_folder", "r") as f:  # Attempt to open a directory as a file
        content = f.read()
except IsADirectoryError as e:
    print("Caught IsADirectoryError:", e)
Caught IsADirectoryError: [Errno 21] Is a directory: 'my_folder'

NotADirectoryError¶

  • Raised when a path operation expects a directory, but the target is not a directory.
In [30]:
try:
    # Suppose "file.txt" is a regular file, not a directory
    with open("file.txt", "w") as f:
        f.write("Hello, Intensity Coding!")

    # Attempt to list contents of a file as if it were a directory
    import os
    os.listdir("file.txt")  # Raises NotADirectoryError

except NotADirectoryError as e:
    print("Caught NotADirectoryError:", e)
Caught NotADirectoryError: [Errno 20] Not a directory: 'file.txt'

RecursionError¶

  • Raised when the maximum recursion depth is exceeded.
  • Happens if a recursive function keeps calling itself without a base condition.
In [27]:
try:
    # Recursive function without a base condition
    def infinite_recursion():
        return infinite_recursion() + 1

    infinite_recursion()  # This will exceed recursion depth

except RecursionError as e:
    print("Caught RecursionError:", e)
Caught RecursionError: maximum recursion depth exceeded

StopIteration¶

  • A StopIteration exception is raised when an iterator has no more items to return.
  • Happens commonly with manual iteration using next(). Python automatically handles it in for loops, but when using next() directly, it must be handled.
In [24]:
# Create a simple iterator
numbers = iter([10, 20, 30])

try:
    print(next(numbers))  # 10
    print(next(numbers))  # 20
    print(next(numbers))  # 30
    print(next(numbers))  # No more items, raises StopIteration
except StopIteration as e:
    print("Caught StopIteration: No more elements in the iterator")
10
20
30
Caught StopIteration: No more elements in the iterator

SyntaxError¶

  • A SyntaxError occurs when Python encounters invalid syntax.
  • For example, forgetting a colon in a function definition.
In [23]:
# Incorrect syntax: missing colon after function definition
def greet()
    print("Hello, Intensity Coding!")
  File "/tmp/ipython-input-2486299230.py", line 2
    def greet()
               ^
SyntaxError: expected ':'

IndentationError¶

  • An IndentationError happens when the code blocks are not properly indented according to Python rules
In [21]:
# Incorrect indentation: the print statement is not indented properly
if 7 > 2:
print("Seven is greater than two!")
  File "/tmp/ipython-input-3383252422.py", line 3
    print("Seven is greater than two!")
    ^
IndentationError: expected an indented block after 'if' statement on line 2

TypeError¶

  • A TypeError occurs when an operation is applied to data of an incompatible type.
In [16]:
x = "5"      # string
y = 3        # integer

# Attempting an invalid operation
try:
    result = x + y   # Python does not know how to add str + int
except TypeError as e:
    print("TypeError occurred:", e)

# Expected Output:
# TypeError occurred: can only concatenate str (not "int") to str
TypeError occurred: can only concatenate str (not "int") to str

ValueError¶

  • Occurs when there is a incorrect value in a specified data type
In [14]:
value = "abc"
try:
    num = int(value)   # Python cannot convert alphabetic characters to int
except ValueError as e:
    print("ValueError occurred:", e)

# Expected Output:
# ValueError occurred: invalid literal for int() with base 10: 'abc'
ValueError occurred: invalid literal for int() with base 10: 'abc'

UnicodeDecodeError¶

  • Raised when Python tries to decode bytes into a string but the given byte sequence is invalid for the specified encoding.
  • Common when reading files with the wrong encoding.
In [11]:
# Example: Wrong decoding attempt
data = b"\xe2\x28\xa1"  # Invalid UTF-8 sequence

try:
    text = data.decode("utf-8")
except UnicodeDecodeError as e:
    print("UnicodeDecodeError occurred:", e)

# Expected Output:
# UnicodeDecodeError occurred: 'utf-8' codec can't decode byte 0xe2 in position 0: invalid continuation byte
UnicodeDecodeError occurred: 'utf-8' codec can't decode byte 0xe2 in position 0: invalid continuation byte

UnicodeEncodeError¶

  • Raised when Python tries to encode a Unicode string into bytes, but the target encoding cannot represent some characters.
  • Frequently appears while writing text containing emojis or non-ASCII characters to ASCII-only outputs.
In [4]:
# Encoding a string with characters ASCII cannot handle
text = "Intensity Coding – Python ✨"

try:
    encoded = text.encode("ascii")
except UnicodeEncodeError as e:
    print("UnicodeEncodeError occurred:", e)

# Expected Output:
# UnicodeEncodeError occurred: 'ascii' codec can't encode character '\u2013' in position 17: ordinal not in range(128)
UnicodeEncodeError occurred: 'ascii' codec can't encode character '\u2013' in position 17: ordinal not in range(128)

BaseExceptionGroup¶

  • Represents a group of exceptions raised together (Python 3.11+).
  • This feature is especially useful in concurrent or asynchronous tasks where multiple failures can occur in parallel.
  • Traditional exception handling works well when a program raises one error at a time, but breaks down when multiple independent tasks fail concurrently.
  • BaseExceptionGroup provides a structured way to bundle many exceptions together and raise them as a single object.
  • The idea is simple: Instead of raising a single exception, you can raise a collection of exceptions wrapped inside an exception group.

Why Do We Need Exception Groups?

  • Consider asynchronous execution:
    • Several tasks run concurrently.
    • Multiple tasks fail at the same time.
    • Traditional exception handling captures only one exception.
  • Exception groups solve this puzzle by allowing the program to raise, propagate, and handle several exceptions in a structured way.

BaseExceptionGroup vs. ExceptionGroup

Class Purpose
BaseExceptionGroup Low-level base class for groups of exceptions
ExceptionGroup Derived class used for normal exceptions
  • ExceptionGroup behaves like a normal exception but holds multiple sub-exceptions.

Structure of Exception Groups

  • Basic Form : BaseExceptionGroup(message, exceptions)
  • Key Attributes :
    • message: A description of the group.
    • exceptions: A list of contained exceptions (or nested groups).
  • Example :
ExceptionGroup(
    "Group message",
    [
        ValueError("invalid data"),
        TypeError("wrong type"),
        ExceptionGroup(
            "Nested group",
            [
                RuntimeError("inner failure"),
                KeyError("missing field")
            ]
        )
    ]
)
  • Each element in the group is either:
    • a single exception
    • another exception group
In [ ]:
# Example of grouping multiple exceptions
try:
    raise BaseExceptionGroup("Multiple errors", [ValueError("v"), TypeError("t")])
except BaseExceptionGroup as eg:
    print("Caught group:", eg)
# Output: Caught group: Multiple errors (2 sub-exceptions)
Caught group: Multiple errors (2 sub-exceptions)
Example: Raising an Exception Group¶
In [ ]:
def run_tasks():
    errors = []

    # Task 1: division by zero
    try:
        10 / 0
    except Exception as e:
        errors.append(e)

    # Task 2: invalid conversion
    try:
        int("abc")
    except Exception as e:
        errors.append(e)

    # If multiple tasks failed, group them
    if errors:
        raise ExceptionGroup("Multiple task failures in Intensity Coding", errors)


try:
    run_tasks()
except ExceptionGroup as eg:
    print(eg)
    print("Exception Group Caught:")
    for err in eg.exceptions:
        print(" -", repr(err))

# Expected Output:
#Multiple task failures in Intensity Coding (2 sub-exceptions)
# Exception Group Caught:
#  - ZeroDivisionError('division by zero')
#  - ValueError("invalid literal for int() with base 10: 'abc'")
Multiple task failures in Intensity Coding (2 sub-exceptions)
Exception Group Caught:
 - ZeroDivisionError('division by zero')
 - ValueError("invalid literal for int() with base 10: 'abc'")
Using except* for Selective Handling¶
  • Python 3.11 introduced a new handler:
except* ExceptionType:
  • It was designed specifically for working with exception groups, where several independent errors are raised together.

  • The normal except block is not enough in this situation because it attempts to match an entire exception group. In contrast, except* extracts only the exceptions of a particular type, handles them, and leaves the rest untouched.

  • This makes it possible to respond differently to each type of failure even when they appear in the same group.

How except* Behaves

  • When an exception group reaches the except* blocks, Python performs the following steps:

    1. Scan the group for exceptions matching the target type.
    2. Split the group into subgroups:
      • one subgroup containing only the matching exceptions,
      • another containing everything else.
    3. Run the block using the matching subgroup.
    4. Re-raise the remainder, unless later except* blocks handle them.

Example: Selectively Handling Different Errors

In [ ]:
# Example: selective handling
try:
    # Construct a group with multiple different exception types
    raise ExceptionGroup(
        "Example group",
        [
            ValueError("invalid configuration"),
            TypeError("unsupported parameter type"),
            ZeroDivisionError("division by zero occurred")
        ]
    )
# Handle only the ValueError inside the group
except* ValueError as group_val:
    print("Handled ValueError subgroup:", group_val)

# Handle only the ZeroDivisionError inside the group
except* ZeroDivisionError as group_zero:
    print("Handled ZeroDivisionError subgroup:", group_zero)

# Remaining exceptions (e.g., TypeError) propagate upward
Handled ValueError subgroup: Example group (1 sub-exception)
Handled ZeroDivisionError subgroup: Example group (1 sub-exception)
---------------------------------------------------------------------------
ExceptionGroup                            Traceback (most recent call last)
/tmp/ipython-input-600235792.py in <cell line: 0>()
      2 try:
      3     # Construct a group with multiple different exception types
----> 4     raise ExceptionGroup(
      5         "Example group",
      6         [

ExceptionGroup: Example group (1 sub-exception)
  • Explained Output : The actual printed lines will be:
Handled ValueError subgroup: Example group (1 sub-exception)
Handled ZeroDivisionError subgroup: Example group (1 sub-exception)
  • After these handlers run, only one exception remains:
TypeError("unsupported parameter type")
  • Because no except* TypeError is present, Python re-raises a new exception group containing just that TypeError:
ExceptionGroup: Example group (1 sub-exception)
  • This shows how each except* block isolates and processes only the types it is designed to handle.
Category
Python Natural Language Processing Generative AI
Tag's
Python Natural Language Processing

Quick Links

  • Home
  • Tutorials
  • About Us
  • Contact Us

Tutorials

  • Python
  • Natural Language Processing
  • Generative AI

Tags

  • Python
  • Natural Language Processing

About Intensity Coding

  • Intensity Coding is your learning hub for Data Science, Machine Learning, Deep Learning, NLP, and Generative AI. From beginner to expert level, we offer clear tutorials, real-world examples, and up-to-date insights. Our content simplifies complex topics to help you grow in your AI journey.
Intensity Coding

© 2025 Intensity Coding. All Rights Reserved.

Privacy Policy Terms and Conditions Disclaimer