I would like to remove the last row appended to a CSV file (sort of like 'undo' last appended row). So far I have an interface that takes a user-generated raw_input and performs a command. For instance, 'a' adds the row to the CSV file, 'r' rejects the row from the CSV file. I would like 'u' to remove the last row added to the CSV file. My code looks like this
for i in range(0,len(out['bestObjID']),1):
j = raw_input('\n Add (a) or Reject (r)?: ')
if j=='ADD' or j=='add' or j=='a' or j=='A':
c = csv.writer(open('NLS1_candidates.csv','a+'))
c.writerow(out[i])
print(' Writing object to candidate list...')
i += 1
elif j=='REJECT' or j=='reject' or j=='r' or j=='R':
print(' Object rejected...')
i += 1
elif j=='UNDO' or j=='undo' or j=='u' or j=='U':
i -= 1
elif j=='?' or j=='h' or j=='help' or j=='HELP' or j=='H':
print(' \n Press (a) to add object to candidate list')
print(' Press (r) to add to reject object')
print(' Press (?) or (h) for help')
print(' Press (q) to Quit')
elif j=='q' or j=='Q' or j=='QUIT' or j=='quit':
print('\n Quitting...')
break
else:
print(' \n Press (a) to add object to candidate list')
print(' Press (r) to add to reject object')
print(' Press (?) or (h) for help')
print(' Press (q) to Quit')
How would I go about adding 'undo' functionality to my CSV file?
Edit: I've failed to mention that when I add a row to the CSV file, out[i]
is a row read from another CSV file. If that helps at all.
If your file is not large, you can store them in a list by readlines()
and remove the last row, and then write to the file with the same filename.
cat sample.csv
line1
line2
line3
cat test.py
inputs = open("sample.csv")
all_lines = inputs.readlines()
all_lines.pop(len(all_lines)-1) # removes last line
inputs.close() # closes file
# truncate file and write all lines except the last line
with open("sample.csv", "w") as out:
for line in all_lines:
out.write(line.strip() + "\n")
python test.py
cat sample.csv
line1
line2
A (dirty) solution can be to write each line by specifing the EOF character ( \\n
probably) at the beginning, and, when the last line should be deleted, to write the \\r
character .
But this don't handle multiple line deletion.
In case of a very large file, a solution is to define a NB_UNDO_LIMIT
integer, which is equal to the number of lines saved in memory before writing, allowing the user to undo at most NB_UNDO_LIMIT
times the addition.
from collections import deque
NB_UNDO_LIMIT = 10
output = open('output', 'w')
float_lines = deque(maxlen=NB_UNDO_LIMIT)
for line in open('filename'):
# write the older line if necessary
if len(float_lines) == NB_UNDO_LIMIT:
output.write(float_lines.popLeft())
float_lines.append(line)
# do a job on the NB_UNDO_LIMIT last lines
The following is untested, but should give you a basic idea of how it could be done. One of the reasons I asked whether your current code works was because of the manual manipulation of the i
variable inside the for i in range(...):
loop. Seems like it could cause problems...
last_write = None
for i in range(0,len(out['bestObjID']),1):
j = raw_input('\n Add (a) or Reject (r)?: ')
if j=='ADD' or j=='add' or j=='a' or j=='A':
with open('NLS1_candidates.csv', 'ab+') as f:
f.seek(0, os.SEEK_END)
last_write = f.tell() # remember where added row starts
c = csv.writer(f)
print(' Writing object to candidate list...')
c.writerow(out[i])
elif j=='REJECT' or j=='reject' or j=='r' or j=='R':
print(' Object rejected...')
i += 1
elif j=='UNDO' or j=='undo' or j=='u' or j=='U':
if last_write is None:
print(' Nothing to undo!')
else:
with open('NLS1_candidates.csv', 'ab+') as f:
f.seek(last_write) # go back to where last row started
print(' Removing last row added.')
f.truncate() # reset file size back to that point
last_write = None
i -= 1
elif j=='?' or j=='h' or j=='help' or j=='HELP' or j=='H':
print(' \n Press (a) to add object to candidate list')
print(' Press (r) to add to reject object')
print(' Press (?) or (h) for help')
print(' Press (q) to Quit')
elif j=='q' or j=='Q' or j=='QUIT' or j=='quit':
print('\n Quitting...')
break
else:
print(' \n Press (a) to add object to candidate list')
print(' Press (r) to add to reject object')
print(' Press (?) or (h) for help')
print(' Press (q) to Quit')
*This will work only when you do not have successive UNDOs.
If you make some changes to file.csv, then the previous copy of that would be stored in file.csv~ Just do a file replace to get back the previous content.
Thanks to wfgeo
: another and I guess a simple solition is to use os
library, find the last row and truncate it:
import csv
import os
with open(fileName, 'w', newline='') as f:
writer = csv.writer(f, delimiter=';', dialect='excel')
for row in rows:
row = rows[0].values()
writer.writerow(row)
f.seek(0, os.SEEK_END)
f.seek(f.tell()-2, os.SEEK_SET)
f.truncate()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.