1

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,[email protected],400
smithC,open123,[email protected],200
blogsJ,2bg123,[email protected],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?

5 Answers 5

2

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.

Sign up to request clarification or add additional context in comments.

6 Comments

simplest answer - brilliant thanks!!! if row[0] != username: works. Could you also add to your answer to include the most efficient /simple way to then write to file(your suggestion of overwriting?)
If you're able to see my UPDATE in the question -and answer it, I can accept your answer, as I've half used it. Thanks
Edited, hope it helps.
Thanks - but this is REALLY odd. You'll notice that here on repl.it - it works (does it?) repl.it/Jhcm/0 ...but when I try it in IDLE with the same text file, it comes up with the error: if row[0]!=username: #as long as the username is not in the row ....... IndexError: list index out of range
not entirely sure what I did - but it works now! repl.it/Jhcm/7 (on both repl.it and IDLE) Thanks
|
2

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!

3 Comments

What if somebody has used "marvR" as their password? Do they deserve to be deleted for that? :(
Thanks flevinkelming - could you see my update and suggest a final solution - I'm nearly there.
@MissComputing your line updatedlist=row should be updatedlist.append(row) - for what you have currently written, the last row that does not contain username is assigned to updatedlist and that row is what you're currently writing to the file, instead of all lines not containing the username.
1

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

4 Comments

This is very helpful - but seems so long. I suppose without the aforementioned numpy or pandas it's going to be long?
I'm confused, why is a transpose of the list necessary?
@TomWyllie I just tried to fix the OPs code for educational reasons. I could write something more simple from scratch, but how would it help? If you run the code you will see that the way OP loaded the list made it ugly nested. So I needed to transpose the indices to find out the index of the name.
@MissComputing I think it could be shorter. Take a look at other answers. But I use pandas. It is a really cool library. I think it is a question of taste
1

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.

Comments

1

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()

3 Comments

interesting. I tried your code exactly and it comes up with if row[0] != username: # as long as the username is not in the row IndexError: list index out of range ...but it sort of works on repl.it - repl.it/Jhcm/2 Any thoughts? Why is it list index out of range on IDLE!? Another error on repl.it
The error on repl.it (os not defined) is because the import os is not present. In IDLE, are there any blank lines at the end of the file?
not entirely sure what I did - but it works now! repl.it/Jhcm/7 (on both repl.it and IDLE) Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.