
Python Exception Handling¶
Introduction to Exception Handling in Python¶
- Exceptions are runtime errors that disrupt normal program execution and disrupt its normal flow.
- 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.
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. |
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.
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.
Handling Exceptions with try
¶
- 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.
- Without exception handling:
# This will crash the program because x is not defined
print(x)
- With exception handling:
try:
print(x)
except:
print("An exception occurred")
# Output:
# An exception occurred
Basic Syntax of try-except¶
try:
# Code that may raise an exception
...
except ExceptionType1:
# Code to handle ExceptionType1
except ExceptionType2:
# Code to handle ExceptionType2
else:
# Code that runs if no exception occurs
finally:
# Code that runs regardless of what happened above
Generic Exception Handling¶
Python also allows you to use a generic
except
block with no specified exception type.This block will catch any exception, making it useful as a fallback for unexpected errors.
Note: Overusing generic
except
: clauses is discouraged, as it can obscure the cause of bugs during development.
try:
# Code that may raise an exception
...
except:
# If there is any exception, then execute this block.
...
else:
# Code that runs if no exception occurs
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.
try:
print(x)
except NameError:
print("Variable x is not defined")
except:
print("Something else went wrong")
# Output:
# Variable x is not defined
Variable x is not defined
- You can also handle multiple exceptions in one line using tuples:
try:
# Some risky operation
...
except (TypeError, ValueError):
print("Caught either a TypeError or ValueError")
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.
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 thetry
orexcept
blocks.It is commonly used for resource clean-up, such as closing files or releasing memory.
try:
print(x)
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
Raising Exceptions Manually¶
- You can explicitly raise or throw exceptions using the
raise
keyword.
Example 1: Raise a general exception¶
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¶
x = "text"
if not isinstance(x, int):
raise TypeError("Only integers are allowed in this section")
# Output:
# TypeError: Only integers are allowed in this section
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) /tmp/ipython-input-6-1064277544.py in <cell line: 0>() 1 x = "text" 2 if not isinstance(x, int): ----> 3 raise TypeError("Only integers are allowed in this section") 4 5 # Output: TypeError: Only integers are allowed in this section
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 theexcept
clause.By doing so, you gain access to the underlying message or cause of the exception, which helps in debugging and logging.
Single Exception with Variable¶
try:
# Code that may raise an error
except ExceptionType as error_variable:
# Use 'error_variable' to access the error details
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 often contains:
A descriptive error message
Sometimes a tuple with additional context (like error code, location, etc.)
Example 1: Single Exception Handling with Argument¶
# 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'
Example 2: Handling Multiple Exceptions with a Shared Variable¶
def process_data(data):
try:
# Trying operations that may raise different errors
result = 100 / data # May raise ZeroDivisionError
print("Converted to string:", int("text")) # May raise ValueError
except (ZeroDivisionError, ValueError) as err:
print("Caught an exception:", err)
# Test with different inputs
process_data(0)
# Output:
# Caught an exception: division by zero
Caught an exception: division by zero
In this example:
The err 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.
User-Defined Exceptions¶
In addition to using built-in exception types like
ValueError
orTypeError
, 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.
Example : Defining a Custom Exception Class¶
# Define custom exception for data validation
class InvalidDataFormat(Exception):
def __init__(self, column_name):
super().__init__(f"Invalid format detected in column: {column_name}")
Raising and Handling the Custom Exception bold text¶
- Once you've defined your custom exception, you can raise it using the
raise
keyword and handle it with a standardtry-except
block:
# Simulate a data preprocessing function
def validate_data_column(column):
if not all(isinstance(item, (int, float)) for item in column):
raise InvalidDataFormat("age")
# Test the validation
try:
sample_data = [25, 30, 'thirty-five', 40]
validate_data_column(sample_data)
except InvalidDataFormat as error:
print("Data validation failed:", error)
# Output:
# Data validation failed: Invalid format detected in column: age
Data validation failed: Invalid format detected in column: age
Python Built-in Exceptions¶
No. | Exception Name | Description |
---|---|---|
1 | ArithmeticError |
Indicates issues in arithmetic or numeric operations (e.g., overflow, division errors). |
2 | AssertionError |
Triggered when an assert statement condition evaluates to false. |
3 | AttributeError |
Raised when an invalid or missing attribute is accessed on an object. |
4 | Exception |
The base class for all built-in exceptions (directly or indirectly inherited). |
5 | EOFError |
Occurs when input() reaches an unexpected end-of-file (EOF) without reading data. |
6 | FloatingPointError |
Raised when a floating-point calculation fails (rare in standard Python). |
7 | GeneratorExit |
Raised automatically when a generator’s close() method is called. |
8 | ImportError |
Indicates failure when trying to import a module that doesn't exist or fails to load. |
9 | IndentationError |
Raised due to incorrect or inconsistent indentation in the code. |
10 | IndexError |
Occurs when trying to access a sequence (like list or string) using an invalid index. |
11 | KeyError |
Raised when a non-existent key is accessed in a dictionary. |
12 | KeyboardInterrupt |
Triggered when the user interrupts execution manually (e.g., Ctrl+C, Ctrl+Z). |
13 | LookupError |
The base class for lookup-related errors like IndexError and KeyError . |
14 | MemoryError |
Raised when Python runs out of memory during execution. |
15 | NameError |
Indicates that a variable or identifier is not defined. |
16 | NotImplementedError |
Signals that a method or functionality hasn’t been implemented in a subclass. |
17 | OSError |
Raised when a system-related operation (e.g., file or process handling) fails. |
18 | OverflowError |
Occurs when a numeric operation exceeds the limits of the number type. |
19 | ReferenceError |
Triggered when a weak reference to an object becomes invalid. |
20 | RuntimeError |
Generic error for situations that don’t fit into any specific exception category. |
21 | StopIteration |
Raised by next() when there are no more items in an iterator. |
22 | SyntaxError |
Occurs when the Python interpreter detects incorrect syntax. |
23 | TabError |
A specific type of IndentationError raised due to mixing tabs and spaces. |
24 | SystemError |
Raised when the interpreter encounters an internal error (not user-related). |
25 | SystemExit |
Raised when the sys.exit() function is called to stop the interpreter. |
26 | TypeError |
Indicates that an operation or function was applied to an object of inappropriate type. |
27 | UnboundLocalError |
Raised when a local variable is accessed before it has been assigned a value. |
28 | UnicodeError |
The base class for Unicode-related encoding/decoding problems. |
29 | UnicodeEncodeError |
Raised during errors in converting Unicode to a specific encoding format. |
30 | UnicodeDecodeError |
Triggered when decoding a byte stream into Unicode fails. |
31 | UnicodeTranslateError |
Occurs when a Unicode translation process fails. |
32 | ValueError |
Raised when a function receives an argument of the correct type but invalid value. |
33 | ZeroDivisionError |
Triggered when a number is divided by zero using / or // operators. |