I have just a few remarks to add to what has already been said.
Restructure Your Loop to Minimize File Opens and try/except Executions
Currently your structure is:
while True:
...
try:
...
stream = open(file, 'a')
...
except ...
...
For each new row you wish to append to the CSV file, you are establishing a try/except block and performing an open call. More efficient would be to re-structure your loop as:
stream = open('file', a)
try:
while True:
...
except ...:
In that way you are opening the output file only once and establishing a try/except only once. This structure does not allow you to catch a missing comma the way you are currently doing it by causing a ValueError
exception when unpacking the split line. By the way, the error message you generate assumes that no comma has been entered when it is equally possible that the user entered more than one comma. There are better ways to validate the input than relying on this method, as we shall see later.
Terminate Input with an Empty Line
Currently, you are expecting the user to terminate entering name/home pairs by signaling EOF. How to do that is platform-dependent and it is questionable that a non-technical user would know how to do this on any platform. Better to request that the user terminate input with an empty line.
Be More Flexible With What May Be Entered
The user might inadvertently enter additional spaces such as ' Booboo , My House '. You would want to strip leading and trailing whitespace on both the name and house.
The user might want to specify the name using a comma (e.g. 'John, Jr.') or the house with the actual mailing address that has one or more commas (e.g. '1 Main Street, New York'). Using a comma to separate the name from the house disallows these possibilities. One solution is to input the name and house individually with two input
statements. Now there is no reliance on there being exactly one comma entered and a ValueError
raised if this condition is not met.
Alternatively, to support commas as part of name or house, you could do a single input
using a different separator, e.g. '|', which cannot be legally used in a value. Then you split the line and only when you have verified that the result is a list of length two do you do the unpacking. This will help you to generate a more meaningful error message.
But you still have the problem of correctly writing a new row to the CSV file so that commas within a value are not mistaken for additional columns.
One solution that easily allows you to have commas embedded within a value is to use the csv
module, which takes care of outputting the necessary double-quotes around a column when necessary.
Putting It All Together
This is one possibility incorporating these ideas:
import csv
def get_name(student):
return student["name"].capitalize()
CSV_FILE = r"C:\Users\Student\Documents\mywebsites\python projects\students.csv"
with open(CSV_FILE, 'a', newline='') as file:
wtr = csv.writer(file)
while True:
name = input(
"Enter your name or an empty line when done: "
).strip()
if not name:
break
house = input(
"Enter your house or an empty line when done: "
).strip()
if not house:
break
wtr.writerow([name, house])
students = []
with open(CSV_FILE, newline='') as file:
rdr = csv.reader(file)
for row in rdr:
student = {'name': row[0], 'house': row[1] }
students.append(student)
for student in sorted(students, key=get_name):
print(f"{student['name']} is in {student['house']}")