🔒
Pro Content
Subscribe to access all 69 OCR H446 A Level lessons.
£7.99/month
or £59/year
Subscribe now →
🔒 Pro · Component 2 · 2.2.1 Problem Solving & Programming
2.2.1b File Handling and Exception Handling
OCR H446 · A Level Computer Science · ~16 min read
Notes
Video
Slides
Worksheet
Quiz

File Handling

Programs often need to persist data between runs. Files provide permanent storage on disk. File handling covers opening, reading, writing, appending, and closing files. In Python, the open() function is used with a mode specifying how to interact with the file.

File Modes

ModeDescriptionFile must exist?
'r'Read — read from start of fileYes — FileNotFoundError if not
'w'Write — overwrite entire file (or create if absent)No — creates new file
'a'Append — add to end of fileNo — creates if absent
'r+'Read and writeYes
'b'Binary mode (combine: 'rb', 'wb')Depends on base mode

Reading Files

# Method 1: read entire file as a string
with open('data.txt', 'r') as f:
    content = f.read()

# Method 2: read line by line
with open('data.txt', 'r') as f:
    for line in f:
        print(line.strip())   # strip removes trailing newline

# Method 3: read all lines into a list
with open('data.txt', 'r') as f:
    lines = f.readlines()     # list of strings, each ending in \n

Writing Files

# Write (overwrites existing content)
with open('output.txt', 'w') as f:
    f.write("Hello, World!\n")
    f.write("Second line\n")

# Append (adds to end, preserves existing content)
with open('log.txt', 'a') as f:
    f.write("New log entry\n")

The with Statement

The with statement (context manager) automatically closes the file when the block exits, even if an exception is raised. This prevents resource leaks — a file left open consumes a file handle (OS resource). Always use with open(...) instead of f = open(...) with a separate f.close().

CSV Files

CSV (Comma-Separated Values) files store tabular data. Python's csv module handles them correctly (dealing with commas inside quoted fields, newlines, etc.)

import csv

# Reading CSV
with open('students.csv', 'r') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)   # each row is a list

# Writing CSV
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['Name', 'Grade'])
    writer.writerow(['Alice', 'A'])

Exception Handling

An exception is an error that occurs at runtime, interrupting normal program flow. Without handling, exceptions cause the program to crash. Exception handling allows a program to detect errors, respond to them gracefully, and continue running where appropriate.

try / except / else / finally

try:
    # Code that might raise an exception
    number = int(input("Enter a number: "))
    result = 100 / number

except ValueError:
    # Handle specific exception type
    print("Not a valid number!")

except ZeroDivisionError:
    print("Cannot divide by zero!")

except Exception as e:
    # Catch any remaining exception
    print(f"Unexpected error: {e}")

else:
    # Runs only if no exception was raised
    print(f"Result: {result}")

finally:
    # Always runs — even if exception occurred
    print("Done.")

Common Exception Types

ExceptionCause
ValueErrorArgument of wrong value (e.g. int("abc"))
TypeErrorWrong type (e.g. "5" + 5)
ZeroDivisionErrorDivision by zero
FileNotFoundErrorFile does not exist
IndexErrorList index out of range
KeyErrorDictionary key not found
NameErrorVariable not defined
OverflowErrorResult too large to represent

Raising Exceptions

Code can raise (throw) its own exceptions using the raise keyword. This is useful for enforcing preconditions or signalling invalid states to the caller.

def set_age(age):
    if age < 0 or age > 150:
        raise ValueError(f"Invalid age: {age}")
    return age

Custom Exceptions

Create custom exception types by inheriting from Exception:

class InsufficientFundsError(Exception):
    def __init__(self, amount):
        super().__init__(f"Insufficient funds: need {amount} more")
        self.amount = amount

# Using the custom exception
raise InsufficientFundsError(50)

Exception Handling with File I/O

try:
    with open('data.txt', 'r') as f:
        content = f.read()
except FileNotFoundError:
    print("File not found — creating empty file")
    with open('data.txt', 'w') as f:
        f.write("")
except PermissionError:
    print("Access denied — cannot read file")
Exam tip: Know try/except/else/finally. The else block runs only when NO exception occurred. The finally block ALWAYS runs. These are commonly tested in exam questions asking you to trace code with exceptions.
Exam tip: Always use the with statement for file handling — it automatically closes the file and handles exceptions during I/O. For multiple exception types, list them in order from most specific to most general (catch ValueError before Exception).
✓ Notes completed!
Video coming soon
Click to advance · Arrow keys also work
Click slide or press arrow keys to navigate

Worksheet — 2.2.1b File Handling & Exception Handling

8 questions · 22 marks · instantly marked

Q1State the purpose of each file mode: 'r', 'w', 'a'. For each, state whether the file must already exist.[3 marks]
✓ Mark scheme
'r' (read): opens for reading from the start; the file must already exist — FileNotFoundError is raised if it doesn't [1]. 'w' (write): opens for writing — overwrites the entire file if it exists, or creates a new file if it doesn't [1]. 'a' (append): opens for writing at the end of the file — preserves existing content; creates a new file if it doesn't exist [1].
Q2Why is the with statement recommended when handling files? What would happen without it if an exception occurs during file reading?[3 marks]
✓ Mark scheme
The with statement automatically closes the file when the block exits, regardless of whether an exception occurred or not [1]. Without it, if an exception is raised during reading, the f.close() call that follows may never be reached [1], leaving the file open and consuming a file handle (OS resource) — this is a resource leak, and if it happens repeatedly, the OS may run out of file handles [1].
Q3Write Python code to open a file called 'scores.txt' in read mode and print each line, stripping trailing whitespace and newlines.[3 marks]
✓ Mark scheme
with open('scores.txt', 'r') as f: [1 — with statement and 'r' mode]
    for line in f: [1 — iterating over file object line by line]
        print(line.strip()) [1 — strip() removes whitespace/newlines]
Alternative: f.readlines() then iterate over the list — also acceptable. strip() is essential as each line includes a trailing \n character.
Q4Explain the four clauses of exception handling in Python: try, except, else, finally. When does each run?[4 marks]
✓ Mark scheme
try: contains the code that might raise an exception — always executed [1]. except: runs only if an exception of the specified type (or any exception if not specified) was raised in the try block — handles the error [1]. else: runs only if NO exception was raised in the try block — often contains code that should only run on success [1]. finally: ALWAYS runs — regardless of whether an exception occurred, was caught, or not — used for cleanup code (closing files, releasing resources) [1].
Q5Name four built-in Python exception types and state what causes each.[4 marks]
✓ Mark scheme
Any 4 of (1 mark per correct pair): ValueError — argument of wrong value, e.g. int("abc") [1]. TypeError — operation on wrong type, e.g. "5" + 5 [1]. ZeroDivisionError — division or modulo by zero [1]. FileNotFoundError — file or directory not found [1]. IndexError — list index out of range [1]. KeyError — dictionary key not found [1]. NameError — variable or name not defined [1]. OverflowError — arithmetic result too large to represent [1].
Q6Write Python code that asks the user to enter an integer and handles both ValueError (not a number) and ZeroDivisionError (divides 100 by the input).[4 marks]
✓ Mark scheme
try: [1 — try block present]
    n = int(input("Enter integer: "))  # may raise ValueError
    result = 100 / n                      # may raise ZeroDivisionError
    print(result)
except ValueError: [1 — handles ValueError]
    print("That is not a valid integer")
except ZeroDivisionError: [1 — handles ZeroDivisionError]
    print("Cannot divide by zero") [1 — both exceptions caught separately with appropriate messages]
Q7Explain how to create and raise a custom exception class in Python. Give an example.[3 marks]
✓ Mark scheme
Create a custom exception by defining a class that inherits from Exception (or a more specific built-in exception) [1]. Example: class InvalidAgeError(Exception): pass — this creates a custom exception type that can be raised and caught like any built-in exception [1]. Raise it with: raise InvalidAgeError("Age must be positive") — the string becomes the exception message [1]. Callers can catch it with: except InvalidAgeError as e: print(e)
Q8Write Python code to read all lines from 'results.txt' and handle the case where the file doesn't exist by printing an error message.[3 marks]
✓ Mark scheme
try: [1 — try block]
    with open('results.txt', 'r') as f: [1 — with statement for file handling]
        lines = f.readlines()      # or: for line in f: print(line)
        print(lines)
except FileNotFoundError: [1 — correct exception type]
    print("Error: results.txt not found")
Topic Quiz
1 of 15
You scored
out of 15
🎯

Mini Test — 2.2.1b File & Exception Handling

  • 10 questions · 10 marks · 10 minutes
  • 5 MCQ + 5 short answer
Card 1 of 15
Click to reveal
🎉
Complete!
TermDefinition
← 2.2.1a Programming Techniques 2.2.1 Problem Solving & Programming Next: 2.2.1c Sets, Maps & Graph Traversal →