Я пытаюсь лучше понять, как обрабатывать файлы с миллионами записей с минимальным использованием памяти.
Для практики я создал файл с ~6,5 миллионами строк и написал пару функций, чтобы разбить его на ~7 файлов по миллиону строк в каждом. В первой функции я использовал метод чтения файла python для создания логики, при которой новый файл создается после чтения 1 миллиона строк, пока мы не найдем последний файл, в котором записаны оставшиеся 500 тысяч строк.
Эта функция работает НАВСЕГДА.
Затем я создал еще одну функцию для разделения файла с помощью itertools.islice. Это заняло чуть менее ~ 2 секунд.
Теперь я знаю, что islice - это итератор, который выполняет итерацию файлового объекта, поэтому ожидается, что он будет более эффективным с точки зрения использования памяти. Однако чем он отличается от метода read()?
Я думал, что даже read() проходит каждую строку в файле одну за другой (что-то вроде итератора..). Итак, я ожидал, что производительность двух программ будет одинаковой. Ребята, помогите мне понять, почему islice НАМНОГО быстрее?
Вот оба фрагмента кода -
1 с использованием чтения () -
with open("bigfile.txt","r") as f:
filenum = 1
j = 1
for i, line in enumerate(f):
if j <= 1000000:
with open("big_out_%d" % filenum, "a") as outfile:
outfile.write(line)
j += 1
if j == 1000000:
j = 1
filenum += 1
with open("big_out_%d" % filenum, "a") as outfile:
outfile.write(line)
2 с использованием islice -
import itertools
import time
start = time.time()
with open("bigfile.txt","r") as f:
i = 1
while True:
chunk = list(itertools.islice(f, 1000000))
if not chunk:
print "reached the end"
break
with open("out%d.txt" % i, "w") as out:
out.writelines(chunk)
print i
i += 1
end = time.time()
print "time is %d" % ((end-start))
read
... Чтение 1M строк по одной или сразу имеет большое значение. Ваш первый выполняет чтение-запись-чтение-запись каждой строки, максимизируя накладные расходы ввода-вывода. - person Andras Deak   schedule 19.05.2019islice
в список, поэтому этот код не выигрывает от того факта, чтоislice
не будет читать все строки сразу. Оказывается, чтение большого фрагмента файла за один раз, а затем запись этого фрагмента одновременно выполняется быстрее, чем чтение и запись построчно. - person ForceBru   schedule 19.05.2019islice
немедленно преобразуется в список, поэтому все 1M строк будут прочитаны сразу, а не лениво, потому что списки не ленивы. - person ForceBru   schedule 19.05.2019f.read()
илиlist(f)
, @ForceBru. - person Andras Deak   schedule 19.05.2019