Exception Handling
Objectives:
- Understand what exceptions are.
- Learn why and where exception handling is used.
- Understand how exception handling improves software reliability.
- Explore Python's exception handling syntax with examples.
- Discuss best practices.
What is an Exception?
An exception is an error that occurs during the execution of a program. When an
exception occurs, the program stops and displays an error message.
Examples of exceptions:
- Division by zero: 5 / 0
- Accessing a variable that doesn't exist.
- Reading a file that is not found.
Why Use Exception Handling?
- To avoid crashing the program due to runtime errors.
- To gracefully handle unexpected situations.
- To provide meaningful messages to users.
- To maintain program flow and allow fallback actions.
Where Do We Use It?
- File operations (file not found, permission error).
- User input (invalid input format).
- Network communication (connection failure).
- Mathematical operations (divide by zero).
- API and database calls (timeouts, missing data).
How Do We Handle Exceptions in Python?
Python uses try, except, else, and finally blocks.
Basic Syntax:
try:
# Code that might raise an exception
except ExceptionType:
# Code to handle the exception
✅ Examples
Example 1: Handling Divide by Zero:
try:
result = 10 / 0 # Trying to divide by zero will raise an exception
except ZeroDivisionError:
print("You can't divide by zero.") # Handle the exception with a custom message
Example 2: Handling Invalid Input:
try:
age = int(input("Enter your age: ")) # User input will be converted to an integer
except ValueError:
print("Invalid input! Please enter a number.") # If input is not a valid number, raise
a ValueError
Using Else and Finally
try:
num = int(input("Enter a number: ")) # Attempt to input an integer
except ValueError:
print("Not a number!") # Catch the ValueError if input is not valid
else:
print("You entered:", num) # If no exception, print the number
finally:
print("This always runs.") # This block runs no matter what
The finally block in Python is used to define code that should always run, no matter what
happens whether an exception occurs or not.
Why Do We Use finally
To clean up resources (e.g., closing files, releasing database connections).
To perform mandatory actions, like logging or displaying a message.
To ensure certain code always executes, even if there's an error.
Common Exception Types in Python
ZeroDivisionError - Dividing by zero
ValueError - Invalid value
TypeError - Operation on incompatible types
FileNotFoundError - File not found
IndexError - List index out of range
KeyError - Dictionary key not found
Best Practices
- Catch specific exceptions (not a generic except).
- Use finally for clean-up actions like closing files.
- Avoid hiding bugs by catching exceptions silently.
- Log errors for debugging.
- Validate inputs before using them.
Python Exception Handling
1. Basic Example – Divide by Zero
try:
x = 10 # Initialize x to 10
y = 0 # Initialize y to 0
result = x / y # Attempt to divide by zero
except ZeroDivisionError:
print("Error: Cannot divide by zero.") # Catch and handle division by zero
exception
2. Multiple Exceptions
try:
name = input("Enter your name: ") # Prompt user for name
age = int(input("Enter your age: ")) # Prompt user for age and convert to int
print(f"{name} is {age} years old.") # Display the name and age
except ValueError:
print("Please enter a valid number for age.") # Handle invalid input for age
except Exception as e:
print("An unexpected error occurred:", e) # Catch any other unexpected exceptions
3. Using else and finally
try:
number = int(input("Enter a number: ")) # Prompt for a number
except ValueError:
print("That was not a number!") # Handle non-integer input
else:
print("You entered:", number) # If no exception, print the number
finally:
print("Program has ended.") # Always runs, even if there's no exception
4. File Handling: Create, Write, Read, Download
Step 1: Create and Write to a File
try:
# Open (or create) a file named "example.txt" in write mode ("w")
# The "with" statement ensures the file is properly closed after writing
with open("example.txt", "w") as file:
# Write a line of text to the file
file.write("Hello, this is a test file.\n") # First line
file.write("It was created in Google Colab.\n") # Second line
file.write("You are learning how to handle files in Python!\n") # Third line
# If everything goes well, print this message
print("✅ File created and data written successfully.")
except Exception as e:
# If any error occurs during writing, show the error
print("❌ An error occurred:", e)
finally:
# This block always runs, whether there's an error or not
print("✅ Finished writing to the file.")
✅ Step 2: Read the Content from the File
try:
# Open the file "example.txt" in read mode ("r")
with open("example.txt", "r") as file:
# Read all content from the file
content = file.read()
# Print the content to the output
print("📄 File Content:")
print(content)
except FileNotFoundError:
# Handle case if file doesn't exist
print("❌ File not found. Please create it first.")
finally:
# Message that this step is completed
print("✅ Finished reading the file.")
✅ Step 3: Download the File to Your Computer (Optional)
from google.colab import files # Import module for file operations
# Use Colab's files.download method to download the file to your local system
files.download("example.txt")
5. Raising Your Own Exceptions
def check_age(age):
if age < 0:
raise ValueError("Age cannot be negative.") # Raise a ValueError if age is
negative
else:
print("Valid age:", age) # Otherwise, print valid age
try:
check_age(-5) # Try to check an invalid age
except ValueError as e:
print("Error:", e) # Catch and print the custom exception message
6. Custom Exceptions
# Step 1: Define a custom exception class
class InvalidAgeError(Exception):
"""Custom exception for invalid age input."""
pass
# Step 2: Function to validate age
def validate_age(age):
if age < 0:
# Raise the custom exception if the age is negative
raise InvalidAgeError("Age cannot be negative.")
else:
print(f"Your age is {age}. Valid age entered.")
# Step 3: Prompt user for input and handle exceptions
try:
age = int(input("Please enter your age: ")) # Ask the user for their age
validate_age(age) # Call the function to validate age
except InvalidAgeError as e:
# Catch the custom exception and print the error message
print(f"Error: {e}")
except ValueError:
# Handle the case where the user doesn't enter a valid number
print("Error: Please enter a valid number for your age.")
Why Use a Custom Exception Here?
The InvalidAgeError custom exception specifically addresses the issue of an
invalid age (in this case, a negative number), which is relevant to the logic of our
program.
Using a custom exception helps make the program’s error-handling more specific
and clear. Instead of using a generic exception like ValueError, we create an
exception that directly explains what went wrong (i.e., negative age).
7. Nested Try Blocks
try:
try:
x = int("abc") # Attempt to convert non-numeric string to integer
except ValueError:
print("Inner exception: Invalid conversion.") # Handle the inner exception
y = 10 / 0 # Division by zero in outer block
except ZeroDivisionError:
print("Outer exception: Division by zero.") # Handle outer exception
8. Using try-except in Loops
for i in range(3): # Loop 3 times
try:
number = int(input("Enter a number: ")) # Try to get an integer input
print("You entered:", number) # If input is valid, print the number
break # Exit loop if input is valid
except ValueError:
print("Please try again with a valid number.") # Handle invalid input
Task: Handle Multiple Exceptions in a Program
Task Description:
Write a Python program that asks the user for a number to divide 100 by. Ensure the
program handles:
1. ZeroDivisionError if the user enters 0.
2. ValueError if the user enters an invalid input (e.g., a non-numeric string).
3. Any other unexpected exceptions.
After handling the exceptions, the program should display the result of the division (if no
error occurred).
Solution:
def divide_number():
try:
number = int(input("Enter a number to divide 100 by: ")) # Take user input
result = 100 / number # Perform division
print(f"100 divided by {number} is {result}")
except ZeroDivisionError:
print("Error: You cannot divide by zero.") # Handle division by zero
except ValueError:
print("Error: Please enter a valid number.") # Handle invalid input (non-numeric)
except Exception as e:
print(f"An unexpected error occurred: {e}") # Handle any other exceptions
divide_number() # Call the function to execute the task
Task: Custom Exception Handling for Age Validation
Task Description:
Create a Python program where the user is prompted to enter their age. If the age entered
is less than 18, raise a custom exception called UnderAgeError and display an appropriate
message. Handle the exception and ask the user to input the age again until a valid age
(18 or older) is entered.
Solution:
# Step 1: Define a custom exception class
class UnderAgeError(Exception):
"""Custom exception for age under 18"""
pass
# Step 2: Function to check age
def check_age():
while True:
try:
age = int(input("Please enter your age: ")) # Prompt user for age
if age < 18:
raise UnderAgeError("You must be 18 or older.") # Raise custom exception if
age is under 18
else:
print(f"Your age is {age}. You are eligible.") # If age is valid
break # Exit the loop if valid age is entered
except UnderAgeError as e:
print(f"Error: {e}") # Handle the custom exception
except ValueError:
print("Error: Please enter a valid number for your age.") # Handle non-integer
input
check_age() # Call the function to validate age