Чтобы написать ленивую функцию, просто используйте yield
:
def read_in_chunks(file_object, chunk_size=1024):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 1k."""
while True:
data = file_object.read(chunk_size)
if not data:
break
yield data
with open('really_big_file.dat') as f:
for piece in read_in_chunks(f):
process_data(piece)
Другим вариантом будет использование iter
вспомогательной функции:
f = open('really_big_file.dat')
def read1k():
return f.read(1024)
for piece in iter(read1k, ''):
process_data(piece)
Если файл основан на строках, объект файла уже является ленивым генератором строк:
for line in open('really_big_file.dat'):
process_data(line)
f = open('really_big_file.dat')
есть строка - это просто указатель без использования памяти? (Я имею в виду, что используемая память одинакова независимо от размера файла?) Как это повлияет на производительность, если я использую urllib.readline () вместо f.readline ()?rb
как упомянул @Tal Weiss; и пропуститьfile.close()
оператор (можно использоватьwith open('really_big_file.dat', 'rb') as f:
для достижения того же; см. здесь для другой краткой реализации'rb'
это не хватает.'b'
его данные будут весьма вероятно , будут повреждены . Из документов -Python on Windows makes a distinction between text and binary files; [...] it’ll corrupt binary data like that in JPEG or EXE files. Be very careful to use binary mode when reading and writing such files.
Если ваш компьютер, операционная система и python являются 64-разрядными , то вы можете использовать модуль mmap для отображения содержимого файла в память и доступа к нему с помощью индексов и фрагментов. Вот пример из документации:
Если ваш компьютер, ОС или python 32-битные , то большие файлы mmap могут зарезервировать большие части вашего адресного пространства и истощить вашу программу памяти.
источник
file.readlines()
принимает необязательный аргумент размера, который приблизительно соответствует количеству прочитанных строк в возвращаемых строках.источник
.read()
не использовать.readlines()
. Если файл является двоичным, у него не будет разрывов строк.Уже есть много хороших ответов, но если весь ваш файл находится в одной строке, и вы все еще хотите обрабатывать «строки» (в отличие от блоков фиксированного размера), эти ответы вам не помогут.
99% времени можно обрабатывать файлы построчно. Затем, как предлагается в этом ответе , вы можете использовать сам объект файла в качестве ленивого генератора:
Тем не менее, я однажды наткнулся на очень и очень большой (почти) файл в одной строке, где разделитель строки был на самом деле не
'\n'
только'|'
.'|'
в'\n'
до обработки также не могло быть и речи, поскольку некоторые из полей этого csv содержали'\n'
(произвольный текст, вводимый пользователем).Для таких ситуаций я создал следующий фрагмент:
Я смог успешно использовать его для решения своей проблемы. Это было тщательно проверено, с различными размерами куска.
Тестовый набор, для тех, кто хочет убедить себя.
источник
ОБНОВЛЕНИЕ: подход лучше всего объяснить в https://stackoverflow.com/a/4566523/38592
источник
Обратитесь к официальной документации Python https://docs.python.org/zh-cn/3/library/functions.html?#iter
Может быть, этот метод более питонический:
источник
Я думаю, что мы можем написать так:
источник
я не могу комментировать из-за своей низкой репутации, но решение SilentGhosts должно быть намного проще с file.readlines ([sizehint])
методы файла Python
редактировать: SilentGhost правильно, но это должно быть лучше, чем:
источник
Я в несколько похожей ситуации. Не ясно, знаете ли вы размер куска в байтах; Обычно я этого не делаю, но количество требуемых записей (строк) известно:
Обновление : спасибо, носкло. Вот что я имел в виду. Это почти работает, за исключением того, что он теряет грань между кусками.
Делает трюк без потери каких-либо линий, но выглядит не очень хорошо.
источник
Чтобы обрабатывать построчно, это элегантное решение:
Пока нет пустых строк.
источник
open
уже дает вам. Файл уже является итератором своих строк.Вы можете использовать следующий код.
open () возвращает объект файла
затем используйте os.stat для получения размера
источник