Practice Programs
Eight programs, and no new syntax in any of them. Every one is csv.writer() or csv.reader() with something ordinary in the loop — a comparison, a counter, a list being built. Read them for the shape, not for the lines.
students.csv and everything after it reads or changes that same file. The transcripts below were run in order, so the file each program sees is whatever the one before it left behind.Roll,Name,Marks
1,Ravi,78
2,Meera,91
3,Amit,6511 · Create a CSV from what the user types
Write a program that asks for a roll number, a name and marks, writes each record into students.csv, and keeps asking until the user says no.
import csv
f = open('students.csv', 'w', newline='')
w = csv.writer(f)
w.writerow(['Roll', 'Name', 'Marks'])
more = 'y'
while more == 'y':
roll = int(input('Roll number : '))
name = input('Name : ')
marks = int(input('Marks : '))
w.writerow([roll, name, marks])
more = input('One more (y/n)? ')
f.close()
print('students.csv is ready.')Roll number : 1 Name : Ravi Marks : 78 One more (y/n)? y Roll number : 2 Name : Meera Marks : 91 One more (y/n)? y Roll number : 3 Name : Amit Marks : 65 One more (y/n)? n students.csv is ready.
w.writerow(['Roll', 'Name', 'Marks'])The header, above the loop, so it is written once.
while more == 'y':A while loop, because nobody knows in advance how many records there will be. more starts as 'y' so the loop runs at least once.
int(input(...))The int() is not needed for the file — writerow() would take the string quite happily. It is there because a roll number is a number, and the habit is worth keeping.
f.close()Outside the loop. Close it once, when there is nothing more to add.
22 · Display every record, and count them
Display the contents of students.csv as a neat table, and print how many records it holds.
import csv
f = open('students.csv', 'r', newline='')
r = csv.reader(f)
header = next(r)
print(header[0], header[1], header[2], sep='\t')
print('-' * 24)
count = 0
for row in r:
print(row[0], row[1], row[2], sep='\t')
count = count + 1
f.close()
print('-' * 24)
print('Records:', count)Roll Name Marks ------------------------ 1 Ravi 78 2 Meera 91 3 Amit 65 ------------------------ Records: 3
count is 3 because next(r) took the header out before the loop started. Count without skipping it and you report 4 — the single most common mistake in this chapter's exam answers.33 · Search for one record
Ask for a roll number and display that student's name and marks. If there is no such student, say so.
import csv
wanted = int(input('Roll number to find: '))
f = open('students.csv', 'r', newline='')
r = csv.reader(f)
next(r)
found = False
for row in r:
if int(row[0]) == wanted:
print('Name :', row[1])
print('Marks:', row[2])
found = True
break
f.close()
if found == False:
print('No student with roll number', wanted)Roll number to find: 2 Name : Meera Marks: 91
Roll number to find: 7 No student with roll number 7
int(row[0]) == wantedrow[0] is the string '2' and wanted is the number 2, and those are never equal. One side has to be converted — here the row is, because that is the value that came out of the file.
found = FalseSet before the loop. Without it there is no way to tell 'nothing matched' from 'the loop has not run yet'.
breakRoll numbers are unique, so there is nothing to gain from reading the rest of the file.
if found == False:Outside the loop, and after f.close(). Inside the loop it would print the message once for every row that did not match.
44 · Add a record to the end
Ask for one new student's details and add them to students.csv without disturbing the records already there.
import csv
roll = int(input('Roll number : '))
name = input('Name : ')
marks = int(input('Marks : '))
f = open('students.csv', 'a', newline='')
w = csv.writer(f)
w.writerow([roll, name, marks])
f.close()
print('Record added.')Roll number : 4 Name : Sneha Marks : 88 Record added.
Roll,Name,Marks
1,Ravi,78
2,Meera,91
3,Amit,65
4,Sneha,88'a', and no header. The file already has one, and writing another would put Roll,Name,Marks in the middle of the data as if it were a student. Change that one letter to 'w' and the other three records are gone before Sneha is written.55 · Find the topper, and count who passed 75
Print the name and marks of the student with the highest marks, and how many students scored more than 75.
import csv
f = open('students.csv', 'r', newline='')
r = csv.reader(f)
next(r)
best_name = ''
best_marks = 0
above = 0
for row in r:
marks = int(row[2])
if marks > best_marks:
best_marks = marks
best_name = row[1]
if marks > 75:
above = above + 1
f.close()
print('Topper :', best_name, 'with', best_marks)
print('Above 75 :', above)Topper : Meera with 91 Above 75 : 3
marks = int(row[2])Converted once, at the top of the loop, and used twice below. Without the int() the comparison compares strings, and '9' > '75' comes out True because it is judged letter by letter.
best_marks = 0Starting at 0 works because marks are never negative. Starting at the first record's marks is the safer habit for data that could be.
one loop, two questionsThe file is read once and both answers come out of the same pass. Opening it twice would work and would be twice the work.
66 · Copy some records into a second file
Copy every student who scored 80 or more into toppers.csv, keeping the header, and report how many were copied.
import csv
fin = open('students.csv', 'r', newline='')
r = csv.reader(fin)
header = next(r)
fout = open('toppers.csv', 'w', newline='')
w = csv.writer(fout)
w.writerow(header)
copied = 0
for row in r:
if int(row[2]) >= 80:
w.writerow(row)
copied = copied + 1
fin.close()
fout.close()
print(copied, 'records copied into toppers.csv')
print(open('toppers.csv', newline='').read())2 records copied into toppers.csv Roll,Name,Marks 2,Meera,91 4,Sneha,88
open() calls, two variables, two close() calls. Name them for their jobs — fin and fout, or f1 and f2 — because using f twice makes the first file impossible to close.Note w.writerow(header): the header row was read out of the first file and written straight into the second, so the copy is a proper CSV rather than a heap of records.
77 · Change one student's marks
Ask for a roll number and new marks, and update that record in students.csv.
There is no way to change one line of a file in place — the new record is rarely the same length as the old one, and everything after it would have to shift. So an update is always three steps, exactly as it was for text files and binary files:
list(csv.reader(f)) — every row, in a list, in memory.
Ordinary Python. Find the row, assign the new value.
Open in 'w' and writerows() the whole list.
import csv
wanted = int(input('Roll number to update: '))
new_marks = int(input('New marks : '))
# 1. read everything into memory
f = open('students.csv', 'r', newline='')
rows = list(csv.reader(f))
f.close()
# 2. change the one row
found = False
for row in rows:
if row[0] != 'Roll' and int(row[0]) == wanted:
row[2] = new_marks
found = True
# 3. write them all back
if found == True:
f = open('students.csv', 'w', newline='')
w = csv.writer(f)
w.writerows(rows)
f.close()
print('Updated.')
else:
print('No such roll number.')Roll number to update: 3 New marks : 72 Updated.
Roll,Name,Marks
1,Ravi,78
2,Meera,91
3,Amit,72
4,Sneha,88rows = list(csv.reader(f))The header is in this list too — it is row zero. That is why it is written back at the end without any special handling.
row[0] != 'Roll'The guard that keeps int('Roll') from raising ValueError. Because the header is in the list, every loop over rows has to step around it.
row[2] = new_marksrow is a list, and lists are mutable — changing it here changes the copy inside rows. This is the whole reason step 1 read into a list rather than looping the file.
if found == True:The file is only rewritten when something actually changed. Without this check, a wrong roll number rewrites the file for no reason — harmless here, but the habit matters.
'w'. They are two different handles on the same file, and the reading one must be finished with before the writing one empties it.88 · Delete a record
Ask for a roll number and remove that student from students.csv.
The same three steps. The only difference is step 2: instead of changing a row, you build a new list of the rows you are keeping.
import csv
wanted = int(input('Roll number to delete: '))
f = open('students.csv', 'r', newline='')
rows = list(csv.reader(f))
f.close()
kept = []
for row in rows:
if row[0] == 'Roll' or int(row[0]) != wanted:
kept.append(row)
f = open('students.csv', 'w', newline='')
w = csv.writer(f)
w.writerows(kept)
f.close()
print(len(rows) - len(kept), 'record deleted')Roll number to delete: 1 1 record deleted
Roll,Name,Marks
2,Meera,91
3,Amit,72
4,Sneha,88len(rows) - len(kept) counts what went.The row[0] == 'Roll' half of the condition is what keeps the header. Written as or, it is checked first — so on the header row the int(row[0]) on the other side never runs, and never raises ValueError.
9Run one yourself
Everything on this page in a single program: build the file, read it back, search it, and change a record.
10The patterns behind all eight
count = 0 before the loop, count = count + 1 inside it under an if. Records, passes, failures — the same three lines.
found = False before the loop, set it True and break on a match, report the failure after the loop.
Hold the best so far in a variable, compare each row against it, replace when the row beats it.
Two files open at once. Read a row, test it, and writerow() the ones that pass.
Read all → change the list → write all back. Never try to edit a line where it sits.
next(r) when reading, writerow() once when creating, nothing at all when appending — and a guard when looping over list(csv.reader(f)).
- 1
Count how many students scored below 40 and print their names.
Hint · Program 5's shape, with the comparison turned round.
- 2
Print the average marks of the whole class.
Hint · Total in one variable and a count in another, then divide.
int(row[2])both times. - 3
Search by name instead of roll number, and handle two students with the same name.
Hint · No break, and count the matches instead of stopping at the first.
- 4
Write a program that adds 5 marks to every student, up to a maximum of 100.
Hint · Read all, loop the list changing row[2], write all back.
- 5
Merge two CSV files with the same columns into a third, with one header at the top.
Hint · next() on both readers; writerow() the header once.
Why does a search program need found = False before the loop?
Which mode adds a record to an existing CSV without losing the others?
How do you change one record in a CSV file?
When looping over rows = list(csv.reader(f)), why does the code check row[0] != 'Roll'?