I have a list of classes in a given student's semester. I want to save this list of classes to a txt file named classes.txt. This acts as a sort of "save" file. When opened again, the program will read the file and know what classes the student is taking.
I do so with the following code:
def write_out():
f_out = open('classes.txt', 'w')
# classes is a list of classes that the student has created
# all the classes are objects which have a few parameters listed below
for course in classes:
f_out.write(str(Course.course_name(course)) ',' str(Course.credits(course)) ',' str() ',' str(Course.assignments(course)) '\n')
The contents of the written file look like this:
Bio,4,[('exam', 100)],[]
calc,4,[('exam', 50)],[]
A Course object is defined by a few parameters:
- A name (i.e. 'Bio')
- Number of credits
- a list of tuples for the course's grading categories(name of category, then weight)
- List of assignments*
*List of assignments is a list of Assignment objects which are defined by a name, category it is, and a grade
I have chosen to leave a category as a tuple as it just seems easier.
My problem arises when I try to read the file when the program is started. While its relatively simple to write the assignments and categories into a list it becomes more difficult to read it back in as there appear to be double quotes when I convert the list of tuples back over for example with the categories.
My question is: How can I read tuples and lists from a txt file more easily into my program?
I started by reading this post but I hit a dead end as this post is more about saving tuples specifically to a file while I have lots of parameters that need to be converted over to objects when starting the program.
I wanted to broaden this post to be more about save files in general to better understand how I should approach this problem.
After reading the file I create a new Course object given the parameters in the save file and add it to a list named 'courses' which can be accessed later.
Side note: I am not even sure that this method is even the most efficient way of doing things so if anyone has a better idea on how I can more effectively save courses to a file then I am 100% open to it. I plan on having a lot of classes and assignments being written to this file so it is important that this is written correctly
Thanks for any help and this was a project I started early on in my learning path so I just wanted to revisit it to see how to save data to files :p
CodePudding user response:
I will provide you a DIY solution, no external libraries, to give an idea of the workflow. The advises given in the comments are more the good but the underline principles should be "similar".
Performance, safety are not considered here, consider it just as a coding refresh for your learning path (or I hope so).
Requirements:
- use a unique separator symbol when writing to a file, it is easier when you will have read it in a second moment. I choose
;
but be free to change it (the,
gives conflicts with lists, & co) - when writing string objects "double double" quote them so that in the file they will be surrounded by doubles quotes (needed for
eval
see next step), so a string should be of the form'"Bio"'
- use
eval
to "resurrect" the string to an object - add write/read methods in the course class. In particular, the reader is a classmethod since it returns an class instance
class Course:
SEP = ';' # should be a unique character(s)
def __init__(self, name, credits_, grading_cats, assignments):
self.name, self.credits, self.grading_cats, self.assignments = self.data = name, credits_, grading_cats, assignments
def __str__(self): # not needed but useful to understand the difference with "write_file_formatter", see 2.
return f'{self.SEP}'.join( str(i) for i in self.data)
def write_file_formatter(self):
return f'{self.SEP}'.join( f'"{i}"' if isinstance(i, str) else str(i) for i in self.data)
@classmethod
def read_file_formatter(cls, course_string):
return cls(*map(eval, course_string.split(cls.SEP)))
# the courses
c1 = Course('Bio', 4, [('exam', 100)], [])
c2 = Course('cal', 4, [('exam', 50)], [])
print(c1.write_file_formatter())
# "Bio";4;[('exam', 100)];[]
print(c2.write_file_formatter())
# "cal";4;[('exam', 50)];[]
# simulate text file
courses_from_file = c1.write_file_formatter() '\n' c2.write_file_formatter()
# "Bio";4;[('exam', 100)];[]
# "cal";4;[('exam', 50)];[]
# simulate read from file
for course in courses_from_file.split('\n'):
c = Course.read_file_formatter(course)
print(type(c), c)
# <class '__main__.Course'> Bio;4;[('exam', 100)];[]
# <class '__main__.Course'> cal;4;[('exam', 50)];[]