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?

3
  • 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. Commented Dec 31, 2021 at 18:52
  • Does this answer your question? Insert line at middle of file with Python? Commented Dec 31, 2021 at 19:09
  • I think that solution doesn't work in csv files Commented Dec 31, 2021 at 19:16

1 Answer 1

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)
Sign up to request clarification or add additional context in comments.

6 Comments

This is a case where using enumerate is arguably less appropriate than using len and range. header = list(range(len(first_row))).
Thank you! As you have guessed, I was using DictWriter for the header. Your solution works great!
@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.
Or even just writer.writerow(range(len(first_row))), though creating a named list has value as documentation.
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.
|

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.