0

I am trying to read and write to the same csv file, to specifically delete a row in a csv file if a certain header contains a value. My csv file looks like this:

Item # Price Quantity Name
1 2.99 1 Muffin 1
2 3.99 2 Muffin 2
3 4.99 3 Cookie 1
4 5.99 4 Cookie 2

I have the following code:

def delete_item(self, item_num):
        self.result[:] = [d for d in self.result if d.get("Item #") != int(item_num)]
        input = open('items2.csv', 'rb')
        output = open('items2.csv', 'wb')
        writer = csv.writer(output)
        for row in csv.reader(input):
            if row[0]!=item_num:
                writer.writerow(row)
                input.close()
                output.close()

This method takes in a item_num that is entered by the user, and deletes it from the list of dictionaries I have. I am also trying to get this specific row deleted from my csv file that the data is stored in. For example, if the user inputs they would like to delete the row that has the Item # of 1, it would delete this row in the csv file.

I have the following method that I believe does so, but understand I cannot read and write to the same csv file at the same time, as it will simply clear it. I know this isnt extremely practical, as it can load up memory, but I need to adjust the same csv file, and know this can be done by reading, closing it, and then writing. How would I do this?

The same CSV file should look like this after it is done if item_num = 2.

Item # Price Quantity Name
1 2.99 1 Muffin 1
3 4.99 3 Cookie 1
4 5.99 4 Cookie 2
py_coder1019
  • 95
  • 1
  • 8

1 Answers1

2

As you said, you can't (or really shouldn't try to) concurrently read and write the same file. There are several options.

  1. If you don't care about preserving the old file:
  • read the whole file in to a dictionary.
  • close the file that is read
  • monkey with the dictionary as needed
  • open and write the same file with the 'w' modifier on the write command to over-write the current contents
  1. If you want to save the orig file (usually a great idea):
  • read the whole file into a dictionary
  • close the file, perhaps rename it to <filename>_orig
  • monkey with the dictionary
  • open a new file with the old name (or in a new folder of mods)
  1. If you are doing this a lot, it starts to smell like a database so:
  • make the jump to sqlite, which is included in core python
  • read/write concurrently to your heart's content.

TL;DR Summary: do the reading / writing operations sequentially

AirSquid
  • 10,214
  • 2
  • 7
  • 31
  • I have a list of dictionaries, that represent what I want in the csv file right now, I am just trying to update the csv file which represented the list of dictionaries before they were changed. Would my process from here be just to "open and write the same file with the 'w' modifier on the write command to over-write the current contents" as you mentioned? – py_coder1019 Sep 20 '22 at 01:30
  • A more scalable and perfectly readable approach is to open the original file and a new file at once, read a row at a time, and either write it immediately to a new file (modified or unmodified) or discard it. When you're done, close the files, and optionally perform an atomic rename to replace the original file with the new one. Your memory requirement is no longer "enough to hold the entire input file's data" and you have an either/or scenario, either 1) The operation completed, and the new data replaced the old data completely, or 2) The operation failed, and the original data is unchanged. – ShadowRanger Sep 20 '22 at 01:33
  • @ShadowRanger Thank you. That should clearly be in the list of options above. – AirSquid Sep 20 '22 at 02:42