Удалить строку из огромного CSV-файла в Python
У меня есть огромный (240 МБ) CSV-файл, в котором 2 верхние строки представляют собой ненужные данные. Я хочу удалить эти ненужные данные и использовать данные, начиная с этого момента.
Я хотел бы знать, каковы наилучшие варианты. Так как это большой файл, создание его копии и редактирование заняло бы много времени. Ниже CSV, например:
junk,,,
,,,,
No,name,place,destination
1,abx,India,SA
То, что я хотел бы иметь
No,name,place,destination
1,abx,India,SA
3 ответа
Просто выбросьте эти строки.
Используйте Dictreader для разбора заголовка
import csv
with open("filename") as fp:
fp.readline()
fp.readline()
csvreader = csv.DictReader(fp, delimiter=',')
for row in csvreader:
#your code here
Вы можете сделать это с хвостом довольно легко
tail -n+3 foo > result.data
Вы сказали, что верхние 3 строки, но пример удалил верхние 2?
tail -n+2 foo > result.data
Вы можете найти больше способов здесь
Из-за того, как работают файловые системы, вы не можете просто удалить строки из файла напрямую. Любой способ сделать это будет обязательно переписывать весь файл с удаленными ошибочными строками.
На всякий случай, перед удалением старого файла вы захотите временно сохранить новый файл, пока не убедитесь, что новый файл был успешно создан. И если вы хотите избежать чтения всего большого файла в память, вам нужно использовать генератор.
Вот генератор, который возвращает каждый элемент из итерируемого (такого как файловый объект) после того, как определенное количество элементов уже было возвращено:
def gen_after_x(iterable, x):
# Python 3:
yield from (item for index,item in enumerate(iterable) if index>=x)
# Python 2:
for index,item in enumerate(iterable):
if index>=x:
yield item
Чтобы упростить ситуацию, мы создадим функцию для записи временного файла:
def write_file(fname, lines):
with open(fname, 'w') as f:
for line in lines:
f.write(line + '\n')
Нам также понадобится os.remove
а также os.rename
функции от os
Модуль для удаления исходного файла и переименования временного файла. И нам понадобится copyfile
от shutil
сделать копию, чтобы мы могли безопасно удалить исходный файл.
Теперь, чтобы сложить все вместе:
from os import remove, rename
from shutil import copyfile
src_file = 'big_file'
tmp_file = 'big_file_temp'
skip = 2
with open(src_file) as fin:
olines = gen_after_x(fin, skip)
write_file(tmp_file, olines)
src_file_copy = src_file + '_copy'
copyfile(src_file, src_file_copy)
try:
remove(src_file)
rename(tmp_file, src_file)
remove(src_file_copy)
except Exception:
try:
copyfile(src_file_copy, src_file)
remove(src_file_copy)
remove(tmp_file)
except Exception:
pass
raise
Однако я хотел бы отметить, что 240 МБ в наши дни не такой большой файл; Вы можете найти это быстрее сделать это обычным способом, так как это сокращает количество повторяющихся операций записи на диск:
src_file = 'big_file'
tmp_file = 'big_file_temp'
skip = 2
with open(src_file) as f:
lines = f.readlines()
for _ in range(skip):
lines.pop(0)
with open(tmp_file, 'w') as f:
f.write('\n'.join(lines))
src_file_copy = src_file + '_copy'
copyfile(src_file, src_file_copy)
try:
remove(src_file)
rename(tmp_file, src_file)
remove(src_file_copy)
except Exception:
try:
copyfile(src_file_copy, src_file)
remove(src_file_copy)
remove(tmp_file)
except Exception:
pass
raise
... или, если вы предпочитаете более рискованный способ:
with open(src_file) as f:
lines = f.readlines()
for _ in range(skip):
lines.pop(0)
with open(src_file, 'w') as f:
f.write('\n'.join(lines))