简体   繁体   中英

delete row from file using csv reader and lists python

there are similar questions on SO to this but none that deal with the specifics that I require.

I have the following code that seeks to delete a row in a file, based on specified user input. The methodology is to

  1. Read file into a list
  2. Delete the relevant row in the list (ideally while reading in the list?)
  3. Over-write file.

It's 2 and 3 that I would like some guidance on as well as comments as to the best solution (for beginners, for teaching/learning purposes) to carry out this sort of simple delete/edit in python with csv reader.

Code

""" ==============TASK
1. Search for any given username
2. Delete the whole row for that particular user

e.g.
Enter username: marvR
>>The record for marvR has been deleted from file.
"""

import csv

#1. This code snippet asks the user for a username and deletes the user's record from file.

updatedlist=[]
with open("fakefacebook.txt",newline="") as f:
  reader=csv.reader(f)
  username=input("Enter the username of the user you wish to remove from file:")
  for row in reader: #for every row in the file
      if username not in updatedlist:
        updatedlist=row #add each row, line by line, into a list called 'udpatedlist'
        print(updatedlist)

 #delete the row for the user from the list?
#overwrite the current file with the updated list?

File contents:

username,password,email,no_of_likes
marvR,pass123,marv@gmail.com,400
smithC,open123,cart@gmail.com,200
blogsJ,2bg123,blog@gmail.com,99

Update

Based on an answer below, I have this, but when it overwrites the file, it doesn't update it with the list correctly, not sure why.

import csv
def main():
    #1. This code snippet asks the user for a username and deletes the user's record from file.
    updatedlist=[]
    with open("fakefacebook.txt",newline="") as f:
      reader=csv.reader(f)
      username=input("Enter the username of the user you wish to remove from file:")
      for row in reader: #for every row in the file
          if row[0]!=username: #as long as the username is not in the row .......
            updatedlist=row #add each row, line by line, into a list called 'udpatedlist'
            print(updatedlist)
    updatefile(updatedlist)

def updatefile(updatedlist):
    with open("fakefacebook.txt","w",newline="") as f:
        Writer=csv.writer(f)
        Writer.writerow(updatedlist)
        print("File has been updated")


main()

It appears to print the updatedfile correctly (as a list) in that it removes the username that is entered. But on writing this to the file, it only prints ONE username to the file.

Any thoughts so I can accept a final answer?

if username not in updatedlist:

To me should be:

if row[0] != username:

Then in a second loop you write updatedlist into your csv file. I would personnally write everything in another file while reading, then in the end delete the old file and replace it by the new one, which makes it one loop only.

Edit:

replace updatedlist=row with updatedlist.append(row) : the first one means overwriting updatedlist with one row while the second one means adding one more row to it.

writerow writes one row, and you give it a list of rows. Use writerows instead and your writing function will work.

You nearly made it all by yourself, which was my objective. Some other answers already give you better (faster, cleaner ...) ways, so I won't.

Something like this should do you, using the csv module. Since you have structured tabular data with defined columns you should use a DictReader and DictWriter to read and write to/from your file;

import csv

with open('fakefacebook.txt', 'r+') as f:
    username = input("Enter the username of the user you wish "
                         "to remove from file:")
    columns = ['username', 'password', 'email', 'no_of_likes']

    reader = csv.DictReader(f, columns)
    filtered_output = [line for line in reader if line['username'] != username]

    f.seek(0)
    writer = csv.DictWriter(f, columns)
    writer.writerows(filtered_output)
    f.truncate()

This opens the input file, filters the out any entries where the username is equal to the desired username to be deleted, and writes what entries are left back out to the input file, overwriting what's already there.

I recommend this approach:

with open("fakefacebook.txt", 'r+') as f:
    lines = f.readlines()
    f.seek(0)

    username = input("Enter the username of the user you wish to remove from file: ")
    for line in lines:
        if not username in line.split(',')[0]:  # e.g. is username == 'marvR', the line containing 'marvR' will not be written
            f.write(line)

    f.truncate()

All lines from the file are read into lines . Then I go back to the beginning position of the file with f.seek(0) . At this point the user is asked for a username, which is then used to check each line before writing back to the file. If the line contains the username specified, it will not be written, thus 'deleting' it. Finally we remove any excess with f.truncate() . I hope this helps, if you have any questions don't hesitate to ask!

I tried to stick to your code: (EDIT: not elegant, but as near as possible to the OPs code)

""" ==============TASK
1. Search for any given username
2. Delete the whole row for that particular user

e.g.
Enter username: marvR
>>The record for marvR has been deleted from file.
"""

import csv

#1. This code snippet asks the user for a username and deletes the user's record from file.

updatedlist=[]
with open("fakefacebook.txt",newline="") as f:
  reader=csv.reader(f)
  username=input("Enter the username of the user you wish to remove from file:")
  content = []
  for row in reader: #for every row in the file 
     content.append(row)

# transpose list  
content = list(map(list, zip(*content)))
print(content)
index = [i for i,x in enumerate(content[0]) if x == username]
for sublist in content:
  sublist.pop(index[0])

print(content)

# transpose list  
content = list(map(list, zip(*content)))

#write back
thefile = open('fakefacebook.txt', 'w')
for item in content:
  thefile.write("%s\n" % item)

But I would suggest to use numpy or pandas

And for another answer: write to a new file and then rename it!

import csv
import os

def main():
    username = input("Enter the username of the user you wish to remove from file:")
    # check it's not 'username'!

    #1. This code snippet asks the user for a username and deletes the user's record from file.
    with open("fakefacebook.txt", newline="") as f_in, \
            open("fakefacebook.txt.new", "w", newline="") as f_out:
        reader = csv.reader(f_in)
        writer = csv.writer(f_out)
        for row in reader: #for every row in the file
            if row[0] != username: # as long as the username is not in the row
                writer.writerow(row)
    # rename new file
    os.rename("fakefacebook.txt.new", "fakefacebook.txt")

main()

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM