Reputation: 573
I have file with scores:
Foo 12
Bar 44
I try to sort it, erase it and than write sorted scores into it. But I get error:
ValueError: I/O operation on closed file
Here is my function:
def Sort():
scores = []
with open("results.txt") as x:
for linia in x:
name,score=linia.split(' ')
score=int(score)
scores.append((name,score))
scores.sort(key=lambda sc: sc[1])
x.truncate()
for name, score in scores:
x.write(name+' '+str(score))
Upvotes: 0
Views: 122
Reputation: 3898
The file remains open only inside the with
block. After that, Python will automatically close it. You need to open it a second time, using a second with
block.
def Sort():
scores = []
with open("results.txt") as x:
# x is open only inside this block!
for linia in x:
name, score=linia.split(' ')
score = int(score)
scores.append((name, score))
scores.sort(key=lambda sc: sc[1])
with open("results.txt", "w") as x:
# open it a second time, this time with `w`
for name, score in scores:
x.write(name + ' ' + str(score))
Sort()
This can also be done using just a single file open. In this case, you open the file in a dual read/write mode (r+) and use truncate
to erase the previous file contents.
def Sort():
scores = []
with open("results.txt", "r+") as x:
for linia in x:
name, score = linia.split(' ')
score = int(score)
scores.append((name, score))
scores.sort(key=lambda sc: sc[1])
# Go to beginning of file
x.seek(0)
# http://devdocs.io/python~3.5/library/io#io.IOBase.truncate
# If no position is specified to truncate,
# then it resizes to current position
x.truncate()
# note that x.truncate(0) does **not** work,
# without an accompanying call to `seek`.
# a number of control characters are inserted
# for reasons unknown to me.
for name, score in scores:
x.write(name + ' ' + str(score) + '\n')
However, personally, I feel that the first approach is better, and you’re less likely to shoot yourself in the foot.
Upvotes: 2