I'm storing the call to a class Task in an array in a .dat file. I'd like to read this file and reconstruct the class calls.
Here's the class that I'm using right now:
class Task:
def __init__(self, name, timespent):
self.name = name
self.timespent = timespent
def __repr__(self):
return repr('Task("%s",%s)'%(self.name, self.timespent))
Here's the reading from the file:
task_list = []
with open("task_list2.dat", "r") as file:
task_list = eval(file.readline())
Here's the writing to the file:
with open("task_list2.dat", "w") as outFile:
print(repr(task_list), file = outFile)
And here's the contents of the file:
['Task("class",20)']
Where "class" is the name of the task.
I understand that the problem has to do with the single quotes around 'Task("class",20)' but I have no clue how to get rid of them. The error message I get says something along the lines of: "str object has no attribute 'name'"
How can I remove those quotes so that I can reconstruct the classes the next time that I read the file?
You really, really, really don't want to try to use repr
and eval
as a serialization format.
If you just used, say, pickle
, you wouldn't have this problem at all:
with open("task_list2.dat", "wb") as outFile:
pickle.dump(task_list, outFile)
with open("task_list2.dat", "rb") as file:
task_list = pickle.load(file)
Much simpler, yes?
But if you want to know how to solve the immediate problem instead of making it irrelevant: You've got multiple problems in your __repr__
method, all of which need to be fixed if you want it to be round-trippable.
repr
on it. You want to return the string representation, not a string representation of the string representation. Just leave out the repr
.repr
of sub-objects, not the str
. If you're using %
-formatting, that means using %r
rather than %s
.Here's how you can write a round-trippable repr for this class:
def __repr__(self):
return 'Task(%r, %r)' % (self.name, self.timespent))
And you can verify that it does what you want:
>>> t = Task('task name', 23.4)
>>> t
Task('task name', 23.4)
>>> eval(repr(t))
Task('task name', 23.4)
Of course in your particular example, just fixing the first problem (removing the spurious call to repr
) would have gotten rid of the single quotes and made that particular example work. You could also hack around that on the read side by calling eval
twice. Or, for this particular example, even by calling eval(s[1:-1])
or eval(s.strip("'"))
. But any "fix" like that is just going to make it harder to debug the general problems you're going to run into once you have, e.g., a name that isn't as simple as a single all-ASCII-letter word.