Удалить строку из огромного 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

Вы можете найти больше способов здесь

https://unix.stackexchange.com/questions/37790/how-do-i-delete-the-first-n-lines-of-an-ascii-file-using-shell-commands

Из-за того, как работают файловые системы, вы не можете просто удалить строки из файла напрямую. Любой способ сделать это будет обязательно переписывать весь файл с удаленными ошибочными строками.

На всякий случай, перед удалением старого файла вы захотите временно сохранить новый файл, пока не убедитесь, что новый файл был успешно создан. И если вы хотите избежать чтения всего большого файла в память, вам нужно использовать генератор.

Вот генератор, который возвращает каждый элемент из итерируемого (такого как файловый объект) после того, как определенное количество элементов уже было возвращено:

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))
Другие вопросы по тегам