На этом шаге мы рассмотрим способ решения этой задачи.
Вместо того чтобы итерировать по файлу построчно, вы хотите итерировать по коллекции записей фиксированного размера или кусочкам ("chunk").
Используйте функции iter() и functools.partial(), чтобы выполнить этот отличный фокус:
from functools import partial RECORD_SIZE = 32 with open('somefile.data', 'rb') as f: records = iter(partial(f.read, RECORD_SIZE), b'') for r in records: . . . .
Объект records в этом примере является итерируемым; он будет производить кусочки фиксированного размера, пока не будет достигнут конец файла.
Однако стоит отметить, что в последнем элементе может быть на несколько байтов меньше, чем ожидается, если размер файла не делится на точную длину
размера записи.
Малоизвестная возможность функции iter() заключается в том, что она может создать итератор, если вы передадите ей вызываемый объект и пороговое значение. Получившийся итератор просто снова и снова вызывает предоставленный вызываемый объект, пока он не вернет пороговое значение, что приведет к завершению итерирования.
В вышеприведенном решении functools.partial используется для создания вызываемого объекта, который читает фиксированное количество байтов из файла каждый раз, когда вызывается. Пороговое значение b" - то, что будет возвращено при попытке чтения файла, когда будет достигнут его конец.
И последнее: в показанном выше решении файл был открыт в бинарном режиме. Для чтений записей фиксированного размера это является наиболее распространенным случаем. В случае же текстовых файлов более распространенным будет построчное чтение (итератор выполняет его по умолчанию).
На следующем шаге мы рассмотрим чтение бинарных данных в изменяемый буфер.