Как удалить строки CSV в python

Я пытаюсь сравнить два файла csv (fileA и fileB) и удалить любые строки из fileA, которые не найдены в fileB. Я хочу иметь возможность сделать это без создания третьего файла. Я думал, что могу сделать это с помощью модуля CSV writer, но теперь я сам догадываюсь.

В настоящее время я использую следующий код для записи данных сравнения из файла B:

removal_list = set()
with open('fileB', 'rb') as file_b:
    reader1 = csv.reader(file_b)
    next(reader1)
    for row in reader1:
        removal_list.add((row[0], row[2]))

Это где я застрял и не знаю как удалить строки:

with open('fileA', 'ab') as file_a:
    with open('fileB', 'rb') as file_b:
        writer = csv.writer(file_a)
            reader2 = csv.reader(file_b)
            next(reader2)
            for row in reader2:
                if (row[0], row[2]) not in removal_list:
                # If row was not present in file B, Delete it from file A.
                #stuck here:  writer.<HowDoIRemoveRow>(row)

3 ответов


это решение использует fileinput С inplace=True, который записывает во временный файл, а затем автоматически переименовывает его в конец имени файла. Ты не можешь!--12-->удалить строки из файла, но вы можете переписать его только с теми, которые вы хотите.

если аргумент ключевого слова inplace=1 перешло к fileinput.input() или FileInput конструктор, файл перемещается в файл резервной копии и стандартный вывод направляется во входной файл (если файл того же имя файла резервной копии, уже существует, он будет заменен молча). Это позволяет написать фильтр, который перезаписывает входной файл на месте.

fileaбыл

h1,h2,h3
a,b,c
d,e,f
g,h,i
j,k,l

fileB

h1,h2,h3
a,b,c
1,2,3
g,h,i
4,5,6

import fileinput, sys, csv

with open('fileB', 'rb') as file_b:
    r = csv.reader(file_b)
    next(r) #skip header
    seen = {(row[0], row[2]) for row in r}

f = fileinput.input('fileA', inplace=True) # sys.stdout is redirected to the file
print next(f), # write header as first line

w = csv.writer(sys.stdout) 
for row in csv.reader(f):
   if (row[0], row[2]) in seen: # write it if it's in B
       w.writerow(row)

fileaбыл

h1,h2,h3
a,b,c    
g,h,i

CSV не является форматом базы данных. Она читается и пишется как единое целое. Вы не можете удалить строки посередине. Поэтому единственный способ сделать это без создания третьего файла-прочитать файл полностью в памяти, а затем записать его без оскорбительных строк.

но в целом лучше использовать третий файл.


как описал Леннарт, вы не можете изменить CSV-файл на месте при итерации по нему.

Если вы действительно против создания третьего файла, вы можете использовать строковый буфер с StringIO, идея заключается в том, что вы создаете новое желаемое содержимое файла A в памяти. В конце вашего скрипта, вы можете записать содержимое буфера за файл

from cStringIO import StringIO


with open('fileB', 'rb') as file_b:
    new_a_buf = StringIO()
    writer = csv.writer(new_a_buf)
    reader2 = csv.reader(file_b)
    next(reader2)
    for row in reader2:
        if (row[0], row[2]) not in removal_list:
            writer.writerow(row)

# At this point, the contents (new_a_buf) exist in memory
with open('fileA', 'wb') as file_a:
    file_a.write(new_a_buf.getvalue())