DAY 6 - Files, Error Handling & Modules
6.1 Reading and Writing Files
Data lives in files. Before you use pandas, it is important to understand how Python handles files at the fundamental level.
Opening a file
file = open("data.txt", "r") # "r" = read mode
content = file.read()
file.close()Always close a file after you are done with it. Forgetting to close files can cause data loss or locked files. The better approach is the with statement.
The with statement (context manager)
with open("data.txt", "r") as file:
content = file.read()
# File is automatically closed here, even if an error occursAlways use with when working with files.
File modes
| Mode | Description |
|---|---|
"r" | Read (default). Error if file does not exist. |
"w" | Write. Creates file if not exists. Overwrites existing content. |
"a" | Append. Creates file if not exists. Adds to the end. |
"r+" | Read and write. |
Reading methods
with open("data.txt", "r") as f:
content = f.read() # read entire file as one string
with open("data.txt", "r") as f:
lines = f.readlines() # read into a list of lines (each with \n)
with open("data.txt", "r") as f:
for line in f: # iterate line by line (memory-efficient)
print(line.strip()) # .strip() removes the \nWriting to a file
with open("output.txt", "w") as f:
f.write("Line 1\n")
f.write("Line 2\n")
# Append without overwriting
with open("output.txt", "a") as f:
f.write("Line 3\n")Working with CSV files (manual approach)
CSV (Comma-Separated Values) is one of the most common data formats. Here is how to read and write them without any library:
# Writing a CSV
headers = ["name", "age", "city"]
rows = [
["Alice", 28, "London"],
["Bob", 34, "Manchester"],
["Charlie", 22, "Edinburgh"],
]
with open("people.csv", "w") as f:
f.write(",".join(headers) + "\n")
for row in rows:
f.write(",".join(str(item) for item in row) + "\n")
# Reading a CSV
with open("people.csv", "r") as f:
lines = f.readlines()
headers = lines[0].strip().split(",")
print("Headers:", headers)
for line in lines[1:]:
values = line.strip().split(",")
record = dict(zip(headers, values))
print(record)Output:
Headers: ['name', 'age', 'city']
{'name': 'Alice', 'age': '28', 'city': 'London'}
{'name': 'Bob', 'age': '34', 'city': 'Manchester'}
{'name': 'Charlie', 'age': '22', 'city': 'Edinburgh'}Understanding this manual process will make pandas feel like magic when you meet it in your course.
6.2 Error Handling
Errors are inevitable. A file might not exist. A user might type text where a number is expected. A network request might fail. Professional code anticipates these problems and handles them gracefully instead of crashing.
Types of errors
- SyntaxError - invalid Python code (found before the programme runs)
- TypeError - wrong type used in an operation:
"hello" + 5 - ValueError - right type, wrong value:
int("hello") - KeyError - dictionary key does not exist:
d["missing"] - IndexError - list index out of range:
lst[99] - FileNotFoundError - file does not exist
- ZeroDivisionError - dividing by zero
Reading a traceback
When Python encounters an error, it prints a traceback - the trail of function calls that led to the error. Always read it from the bottom up: the last line tells you what went wrong, the lines above tell you where.
Traceback (most recent call last):
File "script.py", line 8, in <module>
result = divide(10, 0)
File "script.py", line 3, in divide
return a / b
ZeroDivisionError: division by zerotry / except
try:
result = 10 / 0
except ZeroDivisionError:
print("Error: Cannot divide by zero.")Handling multiple exception types
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return "Error: Division by zero."
except TypeError:
return "Error: Both inputs must be numbers."
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # Error: Division by zero.
print(safe_divide(10, "x")) # Error: Both inputs must be numbers.else and finally
try:
number = int(input("Enter a number: "))
except ValueError:
print("That is not a valid number.")
else:
print(f"You entered: {number}") # runs only if no exception occurred
finally:
print("This always runs.") # runs regardless of success or failurefinally is typically used to release resources (closing files, database connections) - though with with statements this is usually handled automatically.
raise - raising your own exceptions
def set_age(age):
if age < 0 or age > 120:
raise ValueError(f"Invalid age: {age}. Must be between 0 and 120.")
return age
try:
set_age(-5)
except ValueError as e:
print(e) # Invalid age: -5. Must be between 0 and 120.A practical file-reading pattern
def read_file(filepath):
try:
with open(filepath, "r") as f:
return f.read()
except FileNotFoundError:
print(f"File not found: {filepath}")
return None
except PermissionError:
print(f"No permission to read: {filepath}")
return None6.3 Modules and the Standard Library
A module is a Python file containing functions, classes and variables that you can import and use in your own code.
Importing modules
import math
print(math.pi) # 3.141592653589793
print(math.sqrt(144)) # 12.0
print(math.floor(3.9)) # 3
print(math.ceil(3.1)) # 4# Import specific items
from math import sqrt, pi
print(sqrt(25)) # 5.0
print(pi) # 3.141592653589793
# Import with an alias
import math as m
print(m.factorial(5)) # 120Key standard library modules
random
import random
print(random.randint(1, 100)) # random integer between 1 and 100
print(random.random()) # random float between 0.0 and 1.0
print(random.choice(["a","b","c"])) # random item from a list
data = [1, 2, 3, 4, 5]
random.shuffle(data) # shuffle in place
print(data)datetime
from datetime import datetime, date, timedelta
now = datetime.now()
print(now) # 2025-03-17 14:32:10.123456
print(now.strftime("%d/%m/%Y %H:%M")) # 17/03/2025 14:32
today = date.today()
birthday = date(1995, 6, 15)
age_days = (today - birthday).days
print(f"Days since birthday: {age_days}")
tomorrow = today + timedelta(days=1)
print(f"Tomorrow: {tomorrow}")os
import os
print(os.getcwd()) # current working directory
print(os.listdir(".")) # list files in current directory
os.makedirs("output", exist_ok=True) # create a directory safely
print(os.path.exists("data.txt")) # True or False
print(os.path.join("folder", "data.txt")) # OS-appropriate pathsys
import sys
print(sys.version) # Python version info
print(sys.platform) # 'win32', 'darwin', 'linux'
sys.exit() # terminate the programme✏️ Day 6 Exercises
Exercise 6.1 - File Round-Trip
Write a programme that:
- Creates a file called
students.csvwith headersname,score,gradeand at least 5 rows of data. - Reads the file back.
- For each student, converts the score to an integer and prints a formatted summary line.
Hint: use with open(..., "w") to write and with open(..., "r") to read. Use f.readlines() and loop from lines[1:] to skip the header.
Exercise 6.2 - Robust Input Validator
Write a function get_positive_integer(prompt) that:
- Asks the user for input using the given prompt.
- Attempts to convert it to an integer.
- Checks that the integer is positive (greater than 0).
- If either check fails, prints an appropriate error message and asks again.
- Returns the valid integer once a correct value is given.
Hint: use a while True loop with try/except ValueError. Use a nested if to check positivity.
Exercise 6.3 - Date Calculator
Using the datetime module, write a programme that:
- Asks the user for a date in
DD/MM/YYYYformat. - Calculates how many days until (or since) that date from today.
- Prints an appropriate message: “X days to go”, “Today!”, or “X days ago”.
Hint: use datetime.strptime(string, "%d/%m/%Y").date() to parse the user's input. Subtract today's date to get a timedelta. Use .days to get the integer.
Exercise 6.4 - Challenge: Log File Analyser
Create a simple log file manually (or using Python) with the following format - each line is a log entry:
2025-03-01 ERROR Database connection failed
2025-03-01 INFO Server started
2025-03-02 WARNING Disk usage above 80%
2025-03-02 ERROR Timeout on API call
2025-03-03 INFO Backup completed
2025-03-03 ERROR Memory limit exceededWrite a programme that reads the file and prints:
- Total number of log entries.
- Count of each log level (
ERROR,WARNING,INFO). - All
ERRORentries, formatted clearly.
Hint: split each line on whitespace with a limit: line.split(None, 2) splits on any whitespace into at most 3 parts: date, level, message.
📌 Day 6 Summary
| Concept | What you learned |
|---|---|
open() & with | Open files safely; context manager ensures closure |
| File modes | "r", "w", "a" |
.read(), .readlines() | Reading file content |
.write() | Writing to files |
| CSV manual handling | Read/write delimited data without libraries |
try/except/else/finally | Handle errors gracefully |
raise | Raise your own exceptions |
import | Use modules and the standard library |
math, random, datetime, os | Key standard library modules |
Tomorrow is the capstone day. You will get a gentle introduction to Object-Oriented Programming, write your first complete data programme, and take a first look at the libraries waiting for you in your course.