How to Read and Write to the Same csv File?

Question:

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
Asked By: py_coder1019

||

Answers:

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

Answered By: AirSquid

You’re not doing it concurrently like the other user suggests. You’re working with it sequentially, row by row, byte by byte. It’s completely safe. You may even use only a single descriptor doing it. That should do it

def delete_item(self, item_num):
        self.result[:] = [d for d in self.result if d.get("Item #") != int(item_num)]
        editing = open('items2.csv', 'r+b')
        pointer = 0
        for row in csv.reader(editing):
            if row[0] == item_num:
                rest = editing.read()
                editing.seek(pointer)
                editing.write(rest)
                editing.truncate()
                editing.close()
                break
            pointer = editing.tell()

This code assumes there’s only one row with the provided item #

Answered By: Yuri Sh