EH

Exception Handling

Understanding how to handle errors gracefully in programs using exception handling techniques

Learning Objectives

By the end of this lesson, you will be able to:

  • Understand what exception handling is and why it's important
  • Write TRY-EXCEPT blocks in pseudocode to handle exceptions
  • Handle division by zero errors gracefully in programs
  • Manage file handling exceptions when files don't exist or can't be read
  • Validate user input to prevent invalid data from crashing programs
  • Combine multiple exception handling techniques in a single program
  • Write Python code that implements exception handling using try-except blocks
  • Differentiate between different types of exceptions and handle them appropriately

Key Terms

Exception

An error that occurs while a program is running

Exception Handling

Ensuring the program deals with errors gracefully instead of crashing

TRY Block

Contains code that might generate an exception

EXCEPT Block

Catches errors and handles them when they occur

Division by Zero

Common mathematical error when dividing a number by zero

File Handling Exception

Error that occurs when trying to open or read a file that doesn't exist

Input Validation

Checking user input to ensure it's valid before processing

Graceful Degradation

Program continues working even when an error occurs

Pseudocode

Simple language-agnostic code used to design algorithms

What is Exception Handling?

An exception is an error that occurs while a program is running. If not handled, the program will stop and show an error message. Exception handling ensures the program deals with the error gracefully instead of crashing.

Real-Life Example: Calculator App

Think of a calculator app on your phone:

  • What happens if you try to divide by zero?
  • Without exception handling: App crashes with error message
  • With exception handling: Shows "Cannot divide by zero" and continues working
  • This is graceful degradation - the app doesn't crash!

Exception handling makes apps more robust and user-friendly!

Common Examples of Exceptions

Division by Zero

Trying to divide a number by zero (mathematically impossible)

File Not Found

Reading a file that doesn't exist or can't be accessed

Invalid Input

User enters letters when a number is expected

Exception Handling Flow Visualization

Program Starts Normally
Code executes line by line
TRY Block Begins
Risky code that might cause errors
Exception Occurs!
Error happens during execution
Without Exception Handling
Program crashes with error message

Why is Exception Handling Important?

Prevents Crashes

Ensures the program continues to work even when an error occurs

Improves User Experience

Users see clear error messages instead of unexpected program crashes

Handles Common Issues

Problems like invalid input, missing files, or hardware failures are managed effectively

Pseudocode Structure for Exception Handling

Exception handling uses a TRY-EXCEPT block. Here's how it works in Cambridge Pseudocode:

1 TRY
2     <statements that might cause an error>
3 EXCEPT
4     <statements to handle the error>
5 ENDTRY
TRY Block

Contains the code that might generate an exception

Example: Division operation, file opening
EXCEPT Block

Catches the error and handles it

Example: Show error message, use default value

Key Point: The program continues running after the error is handled in the EXCEPT block.

Activity 1: Identifying Exceptions

For each scenario below, identify:

  1. What type of exception would occur?
  2. How could exception handling prevent the program from crashing?
Scenario A: Calculator Division

A calculator program asks for two numbers and divides the first by the second. The user enters 10 and 0.

Scenario B: File Reader

A program tries to open a file called "data.txt" but the file was accidentally deleted.

Solution:
Scenario A: Calculator Division
  • Exception type: Division by zero error
  • Exception handling: Use TRY-EXCEPT block around division operation. In EXCEPT block, show message "Cannot divide by zero" and ask for new number or use default value.
Scenario B: File Reader
  • Exception type: File not found error
  • Exception handling: Use TRY-EXCEPT block around file opening. In EXCEPT block, show message "File not found" and either create new file or ask for different filename.

Check Your Understanding: What is Exception Handling?

Answer
  • [1 mark] An exception is an error that occurs while a program is running
  • [1 mark] If not handled, the program will stop and show an error message
  • [Additional] Examples include division by zero, file not found, invalid input
Answer
  • [1 mark] Prevents crashes: ensures program continues working even when errors occur
  • [1 mark] Improves user experience: users see clear error messages instead of unexpected crashes
  • [1 mark] Handles common issues: problems like invalid input, missing files are managed effectively
Answer
  • [1 mark] TRY keyword followed by statements that might cause an error
  • [1 mark] EXCEPT keyword followed by statements to handle the error
  • [1 mark] ENDTRY keyword to mark the end of the exception handling block
  • [Additional] The TRY block contains risky code, EXCEPT block contains error handling code
Answer
  • [1 mark] Trying to divide a number by zero
  • [1 mark] Reading a file that doesn't exist
  • [Additional] Reaching the end of a file unexpectedly, invalid user input (letters instead of numbers)
Answer
  • [1 mark] The program will stop/crash immediately
  • [1 mark] It will show an error message to the user
  • [Additional] This creates a poor user experience and may cause data loss

Step 1: Handling Division by Zero

One common error is dividing a number by zero, which is not allowed in mathematics. Without exception handling, this will cause the program to crash.

Real-Life Example: Recipe Calculator

Imagine a recipe app that calculates ingredient amounts:

  • Recipe needs 200g flour for 4 servings
  • User wants to calculate for 0 servings (mistake!)
  • App tries: 200 ÷ 0 = ERROR!
  • Without exception handling: App crashes
  • With exception handling: Shows "Cannot calculate for 0 servings"

Exception handling makes the app resilient to user mistakes!

Why Division by Zero is a Problem

Mathematically Impossible

Dividing by zero is undefined in mathematics

Causes Runtime Error

Program tries impossible calculation and crashes

Need for Validation

Must check divisor isn't zero before dividing

Pseudocode Example

Division by Zero Code Simulation

1 DECLARE firstNumber, secondNumber, result AS INTEGER
2 TRY
3     OUTPUT "Enter the first number:"
4     INPUT firstNumber
5     OUTPUT "Enter the second number:"
6     INPUT secondNumber
7     result ← firstNumber DIV secondNumber
8     OUTPUT "Result: ", result
9 EXCEPT
10     OUTPUT "Error: Division by zero is not allowed."
11 ENDTRY

How it works: The division operation (line 7) is inside the TRY block. If secondNumber is 0, an exception occurs. Instead of crashing, the EXCEPT block runs and shows a friendly error message.

Python Example

def divide_numbers():
    try:
        first_number = int(input("Enter the first number: "))
        second_number = int(input("Enter the second number: "))
        result = first_number // second_number
        print(f"Result: {result}")
    except ZeroDivisionError:
        print("Error: Division by zero is not allowed.")

# Test the function
divide_numbers()

Key Points to Remember

  • Always put division operations inside TRY blocks when the divisor comes from user input
  • In Python, division by zero raises a ZeroDivisionError exception
  • The EXCEPT block should provide helpful feedback to the user
  • After handling the exception, the program continues running normally
  • You can use specific exception types (like ZeroDivisionError) to handle different errors differently

Activity 2: Division by Zero Program

Write a program that:

  1. Asks the user to enter two numbers
  2. Divides the first number by the second number
  3. Uses exception handling to catch division by zero errors
  4. Shows the result or an appropriate error message
  5. Allows the user to try again if they want

Task: Write the pseudocode for this program, then convert it to Python.

Solution:
Pseudocode:
DECLARE firstNum, secondNum, result AS INTEGER
DECLARE choice AS STRING
REPEAT
    TRY
        OUTPUT "Enter the first number: "
        INPUT firstNum
        OUTPUT "Enter the second number: "
        INPUT secondNum
        result ← firstNum DIV secondNum
        OUTPUT "Result: ", result
    EXCEPT
        OUTPUT "Error: Division by zero is not allowed."
    ENDTRY
    OUTPUT "Do you want to try again? (yes/no): "
    INPUT choice
UNTIL choice = "no"
Python Code:
def division_program():
    choice = "yes"
    
    while choice.lower() == "yes":
        try:
            first_num = int(input("Enter the first number: "))
            second_num = int(input("Enter the second number: "))
            result = first_num // second_num
            print(f"Result: {result}")
        except ZeroDivisionError:
            print("Error: Division by zero is not allowed.")
        
        choice = input("Do you want to try again? (yes/no): ")

# Run the program
division_program()

Step 2: File Handling Exceptions

Errors in file handling occur when:

  1. The file you're trying to open doesn't exist
  2. You reach the end of the file unexpectedly

Exception handling ensures the program can detect and respond to these errors.

Real-Life Example: Document Editor

Think of Microsoft Word or Google Docs:

  • You try to open "essay.docx" but it was deleted
  • Without exception handling: Program crashes with technical error
  • With exception handling: Shows "File not found. Create new file?"
  • Program continues working instead of crashing

This is how professional software handles missing files!

Common File Handling Errors

File Not Found

The specified file doesn't exist at the given path

Permission Denied

Program doesn't have permission to access the file

Disk Full

No space left to write to the file

Pseudocode Example

File Handling Code Simulation

1 DECLARE filename AS STRING
2 TRY
3     OUTPUT "Enter the file name:"
4     INPUT filename
5     OPEN filename FOR READING
6     WHILE NOT EOF(filename)
7         OUTPUT READ(filename)
8     ENDWHILE
9     CLOSE filename
10 EXCEPT
11     OUTPUT "Error: File not found or unable to read file."
12 ENDTRY

How it works: The file opening operation (line 5) is inside the TRY block. If the file doesn't exist or can't be read, an exception occurs. The EXCEPT block runs and shows a friendly error message instead of crashing.

Python Example

def read_file():
    try:
        filename = input("Enter the file name: ")
        with open(filename, 'r') as file:
            for line in file:
                print(line.strip())
    except FileNotFoundError:
        print("Error: File not found.")
    except IOError:
        print("Error: Unable to read the file.")

# Test the function
read_file()

Key Points to Remember

  • In Python, FileNotFoundError occurs when a file doesn't exist
  • IOError (Input/Output Error) covers various file access problems
  • The with statement automatically closes the file after use
  • You can have multiple EXCEPT blocks to handle different types of file errors
  • Always provide clear error messages so users know what went wrong

Check Your Understanding: File Handling Exceptions

Answer
  • [1 mark] The file you're trying to open doesn't exist
  • [1 mark] You reach the end of the file unexpectedly
  • [Additional] Other exceptions: permission denied, disk full, file in use by another program
Answer
DECLARE filename AS STRING
TRY
    OUTPUT "Enter the file name:"
    INPUT filename
    OPEN filename FOR READING
    WHILE NOT EOF(filename)
        OUTPUT READ(filename)
    ENDWHILE
    CLOSE filename
EXCEPT
    OUTPUT "Error: File not found or unable to read file."
ENDTRY
Answer
  • [1 mark] FileNotFoundError occurs specifically when a file doesn't exist at the given path
  • [1 mark] IOError is more general and covers various input/output problems like permission issues, disk full, or file corruption
Answer
  • [1 mark] File operations can fail for many reasons outside the program's control (file deleted, no permission, disk full)
  • [1 mark] Placing them in TRY blocks allows the program to handle these failures gracefully instead of crashing

Step 3: Validating User Input

Programs often need to validate user input. For example:

  • Ensuring the user enters a number instead of a letter
  • Checking that the input is within an acceptable range

Exception handling allows you to catch errors if the input is invalid.

Real-Life Example: Online Form

Think of an online shopping checkout form:

  • Age field expects a number
  • User accidentally enters "twenty" instead of "20"
  • Without validation: Program crashes or processes incorrectly
  • With validation: Shows "Please enter a valid number"
  • User can correct their mistake and continue

Input validation prevents errors before they happen!

Common Input Validation Scenarios

Wrong Data Type

Entering text when a number is expected

Out of Range

Entering age as 150 when valid range is 0-120

Invalid Format

Entering phone number without digits

Pseudocode Example

Input Validation Code Simulation

1 DECLARE userInput, userNumber AS INTEGER
2 TRY
3     OUTPUT "Enter a number:"
4     INPUT userInput
5     userNumber ← CONVERT_TO_INTEGER(userInput)
6     OUTPUT "You entered: ", userNumber
7 EXCEPT
8     OUTPUT "Error: Invalid input. Please enter a valid number."
9 ENDTRY

How it works: The CONVERT_TO_INTEGER function (line 5) will fail if userInput contains non-numeric characters. This failure triggers the EXCEPT block, which shows a helpful error message instead of crashing.

Python Example

def validate_input():
    try:
        user_input = input("Enter a number: ")
        user_number = int(user_input)
        print(f"You entered: {user_number}")
    except ValueError:
        print("Error: Invalid input. Please enter a valid number.")

# Test the function
validate_input()

Key Points to Remember

  • In Python, int() conversion raises ValueError if the input isn't a valid number
  • Always validate user input - never trust that users will enter correct data
  • You can combine input validation with loops to allow multiple attempts
  • Consider using validation functions for complex validation rules
  • Provide clear, specific error messages to help users correct their input

Check Your Understanding: Input Validation

Answer
  • [1 mark] Users often make mistakes when entering data (typos, wrong format)
  • [1 mark] Without validation, programs may crash or produce incorrect results from bad input
  • [Additional] Validation ensures data integrity and prevents security vulnerabilities
Answer

[1 mark] ValueError exception

Answer
def get_age():
    try:
        age = int(input("Enter your age: "))
        print(f"Your age is: {age}")
    except ValueError:
        print("Error: Please enter a valid number for age.")

# Test the function
get_age()
Answer
  • [1 mark] Use a loop (WHILE or REPEAT-UNTIL) that continues until valid input is received
  • [1 mark] Place the TRY-EXCEPT block inside the loop to catch errors on each attempt
  • [Additional] Example: REPEAT...TRY...EXCEPT...UNTIL valid input received

Step 4: Combining Exception Handling Techniques

You can use multiple EXCEPT blocks to handle different types of errors in the same program. This allows you to provide specific error messages for different problems.

Real-Life Example: Bank App

Imagine a banking application that:

  • Reads account data from a file
  • Performs calculations on balances
  • Accepts user input for transactions
  • Multiple things can go wrong!
  • File might be missing
  • User might enter invalid amounts
  • Calculations might have issues

Professional apps handle ALL possible errors gracefully!

Benefits of Multiple EXCEPT Blocks

Specific Error Messages

Different errors get different, helpful messages

Different Recovery Actions

Each error type can have appropriate recovery

Better Debugging

Easier to identify which type of error occurred

Pseudocode Example

Combined Exception Handling Simulation

1 DECLARE filename AS STRING
2 DECLARE firstNumber, secondNumber, result AS INTEGER
3 TRY
4     OUTPUT "Enter the file name:"
5     INPUT filename
6     OPEN filename FOR READING
7     OUTPUT "Enter the first number:"
8     INPUT firstNumber
9     OUTPUT "Enter the second number:"
10     INPUT secondNumber
11     result ← firstNumber DIV secondNumber
12     OUTPUT "Result: ", result
13     CLOSE filename
14 EXCEPT // File not found
15     OUTPUT "Error: File not found."
16 EXCEPT // Division by zero
17     OUTPUT "Error: Division by zero is not allowed."
18 EXCEPT // Invalid input
19     OUTPUT "Error: Invalid input."
20 ENDTRY

How it works: This program combines file handling, division, and input validation. Multiple EXCEPT blocks handle different error types: file not found, division by zero, and invalid input. Each provides a specific error message.

Python Example

def combined_example():
    try:
        filename = input("Enter the file name: ")
        with open(filename, 'r') as file:
            print("File content:")
            print(file.read())
        
        first_number = int(input("Enter the first number: "))
        second_number = int(input("Enter the second number: "))
        result = first_number // second_number
        print(f"Result: {result}")
    
    except FileNotFoundError:
        print("Error: File not found.")
    except ZeroDivisionError:
        print("Error: Division by zero is not allowed.")
    except ValueError:
        print("Error: Invalid input.")

# Test the function
combined_example()

Key Points to Remember

  • Multiple EXCEPT blocks allow specific handling of different exception types
  • The order of EXCEPT blocks matters - more specific exceptions should come first
  • In Python, you can catch multiple exceptions in one EXCEPT block: except (Type1, Type2):
  • A generic EXCEPT block without specifying exception type catches all exceptions
  • Always close files in a FINALLY block or use with statement for automatic cleanup

Activity 3: Complete Exception Handling Program

Write a complete program that:

  1. Asks the user for a filename and tries to open it
  2. Asks for two numbers and divides them
  3. Handles these specific exceptions:
    • File not found
    • Division by zero
    • Invalid number input
    • Any other unexpected errors
  4. Provides appropriate error messages for each case
  5. Always closes the file properly, even if an error occurs
Solution:
Python Code:
def complete_program():
    filename = input("Enter the file name: ")
    file = None  # Initialize file variable
    
    try:
        # Try to open and read the file
        file = open(filename, 'r')
        content = file.read()
        print("File content:")
        print(content)
        
        # Get numbers from user
        first_num = int(input("Enter the first number: "))
        second_num = int(input("Enter the second number: "))
        
        # Perform division
        result = first_num / second_num
        print(f"Result of division: {result}")
        
    except FileNotFoundError:
        print("Error: The specified file was not found.")
    except ZeroDivisionError:
        print("Error: Cannot divide by zero.")
    except ValueError:
        print("Error: Please enter valid numbers only.")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    finally:
        # Always close the file if it was opened
        if file:
            file.close()
            print("File closed successfully.")

# Run the program
complete_program()

Check Your Understanding: Combining Techniques

Answer
  • [1 mark] Allows specific error messages for different types of errors
  • [1 mark] Enables different recovery actions for different error types
  • [Additional] Makes debugging easier by identifying exactly which error occurred
Answer
  • [1 mark] Code in the FINALLY block always executes, whether an exception occurs or not
  • [1 mark] Used for cleanup operations like closing files or releasing resources
  • [Additional] Ensures important cleanup happens even if an error occurs
Answer
def process_data():
    try:
        filename = input("Enter filename: ")
        with open(filename) as f:
            data = f.read()
        
        num1 = int(input("Enter first number: "))
        num2 = int(input("Enter second number: "))
        result = num1 / num2
        print(f"Result: {result}")
        
    except FileNotFoundError:
        print("Error: File not found")
    except ZeroDivisionError:
        print("Error: Cannot divide by zero")
    except ValueError:
        print("Error: Invalid number entered")
    except Exception as e:
        print(f"Unexpected error: {e}")
Answer
  • [1 mark] The general EXCEPT block will catch all exceptions
  • [1 mark] The specific EXCEPT blocks that come after will never be reached/executed
  • [Additional] Always put specific exception handlers before general ones

Key Takeaways

  • Exception handling prevents program crashes by gracefully managing errors during runtime
  • TRY-EXCEPT blocks are the fundamental structure for exception handling in pseudocode and Python
  • Division by zero is a common mathematical error that must be caught and handled
  • File handling exceptions occur when files don't exist, can't be read, or have permission issues
  • Input validation is essential to handle invalid user input before it causes errors
  • Multiple EXCEPT blocks allow specific handling of different exception types with appropriate error messages
  • In Python, common exceptions include ZeroDivisionError, FileNotFoundError, ValueError, and IOError
  • The order of EXCEPT blocks matters - specific exceptions should come before general ones
  • Always provide clear error messages that help users understand what went wrong and how to fix it
  • Programs with good exception handling are more robust, user-friendly, and professional
  • Real-world applications use exception handling everywhere - from calculator apps to banking software
  • Practice is essential - write programs that intentionally cause exceptions to learn how to handle them properly

Question Bank

Marking Scheme & Answer
  • [1 mark] Exception handling is a way to catch and respond to errors that occur during program execution
  • [1 mark] It prevents programs from crashing when unexpected situations occur
  • [1 mark] Improves user experience by providing clear error messages instead of technical crash reports
  • [1 mark] Allows programs to handle common issues like invalid input, missing files, or mathematical errors gracefully
Marking Scheme & Answer
DECLARE firstNumber, secondNumber, result AS INTEGER
TRY
    OUTPUT "Enter the first number:"
    INPUT firstNumber
    OUTPUT "Enter the second number:"
    INPUT secondNumber
    result ← firstNumber DIV secondNumber
    OUTPUT "Result: ", result
EXCEPT
    OUTPUT "Error: Division by zero is not allowed."
ENDTRY

Mark allocation: 1 mark for variable declaration, 1 mark for TRY block start, 2 marks for correct division logic inside TRY, 1 mark for EXCEPT block with error message.

Marking Scheme & Answer
Pseudocode:
DECLARE filename AS STRING
TRY
    OUTPUT "Enter file name:"
    INPUT filename
    OPEN filename FOR READING
    OUTPUT READ(filename)
    CLOSE filename
EXCEPT
    OUTPUT "File not found error"
ENDTRY
Python Code:
filename = input("Enter file name: ")
try:
    with open(filename, 'r') as file:
        content = file.read()
        print(content)
except FileNotFoundError:
    print("File not found error")

Mark allocation: 1 mark for input, 1 mark for TRY block, 2 marks for correct file handling with 'with' statement, 1 mark for EXCEPT block, 1 mark for correct exception type (FileNotFoundError).

Marking Scheme & Answer
Division by Zero:
  • Occurs when dividing by zero
  • Handle with ZeroDivisionError in Python
  • Solution: Check divisor isn't zero or use TRY-EXCEPT
File Not Found:
  • Occurs when opening non-existent file
  • Handle with FileNotFoundError in Python
  • Solution: Check file exists or use TRY-EXCEPT
Invalid Input:
  • Occurs with wrong data type input
  • Handle with ValueError in Python
  • Solution: Validate input or use TRY-EXCEPT

Mark allocation: 2 marks for each exception type (1 for description, 1 for handling method).

Marking Scheme & Answer
def calculator():
    print("Simple Calculator")
    print("Operations: +, -, *, /")
    
    try:
        num1 = float(input("Enter first number: "))
        operation = input("Enter operation (+, -, *, /): ")
        num2 = float(input("Enter second number: "))
        
        if operation == '+':
            result = num1 + num2
        elif operation == '-':
            result = num1 - num2
        elif operation == '*':
            result = num1 * num2
        elif operation == '/':
            if num2 == 0:
                raise ZeroDivisionError("Cannot divide by zero")
            result = num1 / num2
        else:
            raise ValueError("Invalid operation")
        
        print(f"Result: {result}")
    
    except ValueError as ve:
        print(f"Input error: {ve}")
    except ZeroDivisionError as zde:
        print(f"Math error: {zde}")
    except Exception as e:
        print(f"Unexpected error: {e}")

# Run calculator
calculator()

Mark allocation: 2 marks for input handling, 2 marks for calculation logic, 2 marks for multiple exception handlers, 2 marks for proper error messages and program structure.

Marking Scheme & Answer
Syntax Errors:
  • Occur during parsing/compilation
  • Caused by incorrect code structure
  • Program won't run at all
  • Examples: missing colon, incorrect indentation
Exceptions:
  • Occur during program execution
  • Caused by runtime conditions
  • Program runs but encounters error
  • Examples: division by zero, file not found
Key Difference: Syntax errors are caught before program runs (by interpreter/compiler), while exceptions occur during execution and can be handled with TRY-EXCEPT blocks.
Marking Scheme & Answer
def calculate_average_grades():
    """Read grades from file and calculate average with exception handling"""
    
    while True:
        try:
            filename = input("Enter grades filename: ")
            
            # Read grades from file
            with open(filename, 'r') as file:
                grades = file.readlines()
            
            # Convert to numbers and calculate average
            total = 0
            count = 0
            
            for grade_str in grades:
                grade = float(grade_str.strip())
                if grade < 0 or grade > 100:
                    raise ValueError(f"Grade {grade} is out of range (0-100)")
                total += grade
                count += 1
            
            if count == 0:
                print("No grades found in file")
                return
            
            average = total / count
            print(f"Average grade: {average:.2f}")
            break  # Exit loop on success
            
        except FileNotFoundError:
            print("Error: File not found. Please try again.")
        except ValueError as ve:
            print(f"Error: Invalid grade data - {ve}")
        except ZeroDivisionError:
            print("Error: Cannot calculate average - no valid grades found")
        except Exception as e:
            print(f"Unexpected error: {e}")
            break  # Exit on unexpected errors

# Run the program
calculate_average_grades()

Mark allocation: 2 marks for file reading, 2 marks for grade processing, 2 marks for average calculation, 4 marks for comprehensive exception handling (file not found, invalid data, division by zero, general exceptions).

Marking Scheme & Answer
Defensive Programming:
  • Prevents errors before they occur
  • Uses validation and checks
  • Example: Check divisor isn't zero before dividing
  • Proactive approach
  • Code may have many condition checks
Exception Handling:
  • Handles errors after they occur
  • Uses TRY-EXCEPT blocks
  • Example: Catch ZeroDivisionError when dividing
  • Reactive approach
  • Cleaner code structure
Best Practice: Use both approaches together - defensive programming to prevent expected errors, and exception handling to gracefully manage unexpected errors.