- Write to and read from a file with
with open(...) - Tell the
'r','w'and'a'modes apart - Combine variables, loops, functions, dictionaries and error handling in one program
As soon as a program ends, all its variables are wiped from memory: the game's high score, the grades in a register, the shopping list — all gone. To keep data, you need to write it to a file. In this lesson you will learn to work with files and then combine everything you have learned in this course in one real project — a grade calculator.
Writing and reading files
The open() function opens a file: the first argument is the file name and the second is the mode. The with statement closes the file automatically when the block ends — even if an error happens. encoding='utf-8' makes sure letters such as ö, ş and ç are stored correctly.
| Mode | Meaning | If the file already exists |
|---|---|---|
'r' | read (the default) | its content is read; if there is no file — FileNotFoundError |
'w' | write | the old content is erased |
'a' | append | new text is added at the end |
with open('notes.txt', 'w', encoding='utf-8') as f:
f.write('Python is fun\n')
f.write('Files keep data\n')
with open('notes.txt', encoding='utf-8') as f:
for line in f:
print(line.strip())▸ Expected output
Python is fun Files keep data
write() does not add a newline at the end, so we write the \n ourselves. When you read a file line by line with a for loop, that \n is still at the end of each line — strip() removes it. To get all the lines at once as a list, use readlines():
with open('log.txt', 'w', encoding='utf-8') as f:
f.write('Day 1: started Python\n')
with open('log.txt', 'a', encoding='utf-8') as f:
f.write('Day 2: learned loops\n')
with open('log.txt', encoding='utf-8') as f:
lines = f.readlines()
print(len(lines), 'lines')
print(lines[-1].strip())▸ Expected output
2 lines Day 2: learned loops
If you try to read a file that does not exist, you get a FileNotFoundError. As in the lesson on error handling, you can catch it with try / except:
try:
with open('missing.txt', encoding='utf-8') as f:
print(f.read())
except FileNotFoundError:
print('File not found, starting with an empty list.')▸ Expected output
File not found, starting with an empty list.
Mini project: grade calculator
A teacher keeps students' grades in a simple text file: each line holds a name and grades separated by commas. This format is called CSV (comma-separated values). Our program will read the file, skip broken lines, calculate each student's average and write a report to a new file.
- 1Prepare the data
Write the grades to
grades.csv. We put a deliberate mistake (x) in one line to see how the program reacts. - 2Read and parse the file
Split each line with
split(','): the first part is the name, the rest are grades. Convert them withint()and store them in a dictionary. - 3Catch the errors
int('x')raises aValueError— catch it withtry/except, print a warning and skip that line. - 4Calculate and write the report
Use functions to find the average and the level, write the results to
report.txtand read it back to check.
lines = ['Aysel,5,4,5,5', 'Murad,4,3,4', 'Leyla,5,5,4,5', 'Elvin,3,x,4', 'Nigar,2,3,3']
with open('grades.csv', 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
journal = {}
with open('grades.csv', encoding='utf-8') as f:
for line in f:
parts = line.strip().split(',')
name = parts[0]
try:
journal[name] = [int(m) for m in parts[1:]]
except ValueError:
print(f'Skipped {name}: bad data')
print(journal)▸ Expected output
Skipped Elvin: bad data
{'Aysel': [5, 4, 5, 5], 'Murad': [4, 3, 4], 'Leyla': [5, 5, 4, 5], 'Nigar': [2, 3, 3]}parts[1:] takes every part after the name.Now let's split the calculation into two functions: average returns the mean, and level returns the level as a word (we chose the thresholds ourselves). A dictionary comprehension calculates all the averages in one line, and the result is written to report.txt:
journal = {'Aysel': [5, 4, 5, 5], 'Murad': [4, 3, 4], 'Leyla': [5, 5, 4, 5], 'Nigar': [2, 3, 3]}
def average(scores):
return sum(scores) / len(scores)
def level(avg):
if avg >= 4.5:
return 'excellent'
elif avg >= 3.5:
return 'good'
elif avg >= 2.5:
return 'satisfactory'
return 'needs help'
averages = {name: average(s) for name, s in journal.items()}
with open('report.txt', 'w', encoding='utf-8') as f:
for name, avg in averages.items():
f.write(f'{name}: {avg:.2f} ({level(avg)})\n')
with open('report.txt', encoding='utf-8') as f:
print(f.read().strip())
print(f'Best average: {max(averages.values()):.2f}')▸ Expected output
Aysel: 4.75 (excellent) Murad: 3.67 (good) Leyla: 4.75 (excellent) Nigar: 2.67 (satisfactory) Best average: 4.75
Write every fruit from fruits to the file fruits.txt, one per line (mode 'w'). Then read the file back and print its lines numbered from 1, in the form 1. apple.
fruits = ['apple', 'pomegranate', 'fig']
# 1) write each fruit on its own line to fruits.txt
# 2) read fruits.txt and print: 1. apple, 2. pomegranate, ...▸ Expected output
1. apple 2. pomegranate 3. fig
Mini project: every line of sales.csv has the form product,quantity,price. Read the file and add up the money earned for each product (quantity × price) in a dictionary. Skip a line with bad data using try/except and print Skipped: followed by that line. Finally print the products in alphabetical order in the form cup: 2.00 AZN, and at the very end a Total: line in the same format.
lines = ['pen,3,0.5', 'notebook,2,1.25', 'bag,1,x', 'pen,4,0.5']
with open('sales.csv', 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
totals = {}
# 1) read sales.csv line by line: product,quantity,price
# 2) skip bad lines (print Skipped: and the line)
# 3) add quantity * price to totals[product]
# 4) print the products in alphabetical order, then the Total▸ Expected output
Skipped: bag,1,x notebook: 2.50 AZN pen: 3.50 AZN Total: 6.00 AZN
Key points
with open(name, mode, encoding='utf-8') as f:opens a file and closes it automatically when the block ends.'r'reads,'w'erases and writes, and'a'appends to the end.write()does not add\n;strip()removes the\nfrom lines you read.- Reading a missing file raises
FileNotFoundError— catch it withtry/except. - CSV lines can be split into parts with
split(',').
Check yourself
10 questions. Every correct answer earns XP.