Перезапись строки в том же CSV-файле с помощью dictwriter

У меня есть имена.csv

first_name,last_name
Baked,Beans
Lovely,Spam
John,Bang
Harry,Potter

Я хочу переименовать «Джон Бан» в «Джейсон Стэтхэм» в том же файле. Я пытался использовать file.seek(), но не смог

import csv
with open('/home/tiwari/Desktop/names.csv', 'rw+') as csvfile:
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    reader = csv.DictReader(csvfile)
    for line, row in enumerate(reader):
        rs = sys.getsizeof(row)
        if row['first_name'] == 'John':
            csvfile.seek(-rs)
            writer.writerow({'first_name': 'Jason', 'last_name': 'statham'})

person sujit tiwari    schedule 28.11.2015    source источник


Ответы (1)


Ваш подход не будет работать, если замещающая строка не имеет точно такой же длины, что и исходная строка.

Я предлагаю прочитать все строки, заменить их и записать обратно.

import csv

with open('/home/tiwari/Desktop/names.csv', 'r+') as csvfile:
    reader = csv.DictReader(csvfile)

    rows = []
    for row in reader:
        if row['first_name'] == 'John':
            row['first_name'] = 'Jason'
            row['last_name'] = 'Statham'
        rows.append(row)

    csvfile.seek(0)  # back to begining of the file.
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(rows)
    csvfile.truncate()  # In case of updated content is shorter.
person falsetru    schedule 28.11.2015
comment
Я согласен с вашим предложением, но мне нужно запустить его для миллионов записей, в этом случае сохранение всех их в списке, вероятно, является проблемой памяти и дополнительными накладными расходами. - person sujit tiwari; 28.11.2015
comment
Будет лучше, если у нас будет какое-то решение с тем же указателем чтения или записи. - person sujit tiwari; 28.11.2015
comment
@sujittiwari, тогда вам лучше записать в другой файл (например, names2.csv), а затем переименовать его в names.csv после завершения записи. - person falsetru; 28.11.2015
comment
@sujittiwari, невозможно использовать seek(-n, 1), особенно если длина строки замены и исходной строки различается, как я уже упоминал в ответе. - person falsetru; 28.11.2015
comment
Привет @falsetru, я уже делаю это, но решил сэкономить несколько циклов записи. Спасибо за внимание - person sujit tiwari; 30.11.2015