1

What I want to do is actually as it is written in the title.

with open(path, "r+", newline='') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    list_of_column_names = []
    num_cols = len(next(csv_reader))
    for i in range(num_cols):
        list_of_column_names.append(i)
    fields = list_of_column_names
    with open(example.csv, "r+", newline='') as writeFile:
        csvwriter = csv.DictWriter(writeFile, delimiter=',', lineterminator='\n', fieldnames=fields)
        writeFile.seek(0, 0)
        csvwriter.writeheader()

I want to enumerate the columns which initially doesn't have any column names. But when I run the code, it replaces the data in the first row. For example:

example.csv:

a,b
c,d
e,f

what I want:

0,1
a,b
c,d
e,f

what happens after running the code:

0,1
c,d
e,f

Is there a way to prevent this from happening?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 3
    You'll have to *overwrite* the entire file, because there's no reasonable way to insert a line (i.e. row) into a text file because the length of each one varies. – martineau Dec 31 '21 at 18:52
  • Does this answer your question? [Insert line at middle of file with Python?](https://stackoverflow.com/questions/10507230/insert-line-at-middle-of-file-with-python) – Gwendal Delisle Arnold Dec 31 '21 at 19:09
  • I think that solution doesn't work in csv files – Bilal Sedef Dec 31 '21 at 19:16

1 Answers1

1

There's no magical way to insert a line into an existing text file.

The following is how I think of doing this, and your code is already getting steps 2-4. Also, I wouldn't mess with the DictWriter since you're not trying to convert a Python dict to CSV (I can see you using it for writing the header, but that's easy enough to do with the regular reader/writer):

  1. open a new file for writing
  2. read the first row of your CSV
  3. interpret the column indexes as the header
  4. write the header
  5. write the first row
  6. read/write the rest of the rows
  7. move the new file back to the old file, overwrite (not shown)

Here's what that looks like in code:

import csv

with open('output.csv', 'w', newline='') as out_f:
    writer = csv.writer(out_f)

    with open('input.csv', newline='') as in_f:
        reader = csv.reader(in_f)

        # Read the first row
        first_row = next(reader)
        # Count the columns in first row; equivalent to your `for i in range(len(first_row)): ...`
        header = [i for i, _ in enumerate(first_row)]

        # Write header and first row
        writer.writerow(header)
        writer.writerow(first_row)

        # Write rest of rows
        for row in reader:
            writer.writerow(row)
Zach Young
  • 10,137
  • 4
  • 32
  • 53
  • 1
    This is a case where using `enumerate` is arguably *less* appropriate than using `len` and `range`. `header = list(range(len(first_row)))`. – chepner Dec 31 '21 at 19:48
  • 1
    Thank you! As you have guessed, I was using DictWriter for the header. Your solution works great! – Bilal Sedef Dec 31 '21 at 19:49
  • @chepner, thanks for the suggestion! I disagree :) I copy-pasted your suggestion and looked at it, and... xrange of length of list materialized to a list just doesn't capture the idea for me. If I didn't use enumerate, I'd actually do it OP's way. – Zach Young Dec 31 '21 at 19:54
  • Or even just `writer.writerow(range(len(first_row)))`, though creating a named list has value as documentation. – chepner Dec 31 '21 at 19:55
  • `enumerate` has to create tuples that are subsequently unpacked just to ignore the additional value that made tuples necessary to create in the first place. – chepner Dec 31 '21 at 19:56
  • I'm okay with all that overhead because: 1) it happens once 2) for me, it shows the idea of building a list of indexes very clearly... I have to puzzle less about what the code is doing – Zach Young Dec 31 '21 at 19:58