Как я могу читать большие текстовые файлы в Python, построчно, не загружая их в память?

Мне нужно прочитать большой файл по строкам. Предположим, что файл имеет более 5 ГБ, и мне нужно прочитать каждую строку, но, очевидно, я не хочу использовать readlines(), потому что он создаст очень большой список в памяти.

Как будет работать код ниже для этого случая? Является ли xreadlines само чтение по одному в память? Требуется ли выражение генератора?

f = (line for line in open("log.txt").xreadlines())  # how much is loaded in memory?

f.next()  

Плюс, что я могу сделать, чтобы прочитать это в обратном порядке, так же как команда Linux tail?

Я нашел:

http://code.google.com/p/pytailer/

и

"python head, tail и backward читается строками текстового файла"

Оба работали очень хорошо!

Ответ 1

Я представил этот ответ, потому что Кит, хотя и сжато, не закрывает файл явно

with open("log.txt") as infile:
    for line in infile:
        do_something_with(line)

Ответ 2

Все, что вам нужно сделать, это использовать файл-объект как итератор.

for line in open("log.txt"):
    do_something_with(line)

Еще лучше использовать контекстный менеджер в последних версиях Python.

with open("log.txt") as fileobject:
    for line in fileobject:
        do_something_with(line)

Это также автоматически закроет файл.

Ответ 3

Старый подход к школе:

fh = open(file_name, 'rt')
line = fh.readline()
while line:
    # do stuff with line
    line = fh.readline()
fh.close()

Ответ 4

Вам лучше использовать итератор. Релевантно: http://docs.python.org/library/fileinput.html

Из документов:

import fileinput
for line in fileinput.input("filename"):
    process(line)

Это позволит избежать копирования всего файла в память сразу.

Ответ 5

Вот что вы делаете, если у вас нет новых строк в файле:

with open('large_text.txt') as f:
  while True:
    c = f.read(1024)
    if not c:
      break
    print(c)

Ответ 6

Попробуйте следующее:

with open('filename','r',buffering=100000) as f:
    for line in f:
        print line

Ответ 7

Я не мог поверить, что это может быть так же просто, как это объяснил @john-la-rooy. Таким образом, я воссоздал команду cp, используя строковое чтение и запись. Это CRAZY FAST.

#!/usr/bin/env python3.6

import sys

with open(sys.argv[2], 'w') as outfile:
    with open(sys.argv[1]) as infile:
        for line in infile:
            outfile.write(line)

Ответ 8

За последние 6 лет проект Blaze прошел долгий путь. Он имеет простой API, охватывающий полезное подмножество функций панд.

dask.dataframe заботится о внутреннем размещении, поддерживает много параллелизуемых операций и позволяет легко экспортировать фрагменты обратно в pandas для операций с памятью.

import dask.dataframe as dd

df = dd.read_csv('filename.csv')
df.head(10)  # return first 10 rows
df.tail(10)  # return last 10 rows

# iterate rows
for idx, row in df.iterrows():
    ...

# group by my_field and return mean
df.groupby(df.my_field).value.mean().compute()

# slice by column
df[df.my_field=='XYZ'].compute()

Ответ 9

Как насчет этого? Разделите файл на куски, а затем прочитайте его по строкам, потому что когда вы читаете файл, ваша операционная система будет кэшировать следующую строку. Если вы читаете файл по строкам, вы не используете эффективное использование кэшированной информации.

Вместо этого разделите файл на куски и загрузите весь фрагмент в память, а затем выполните свою обработку.

def chunks(file,size=1024):
    while 1:

        startat=fh.tell()
        print startat #file object current position from the start
        fh.seek(size,1) #offset from current postion -->1
        data=fh.readline()
        yield startat,fh.tell()-startat #doesnt store whole list in memory
        if not data:
            break
if os.path.isfile(fname):
    try:
        fh=open(fname,'rb') 
    except IOError as e: #file --> permission denied
        print "I/O error({0}): {1}".format(e.errno, e.strerror)
    except Exception as e1: #handle other exceptions such as attribute errors
        print "Unexpected error: {0}".format(e1)
    for ele in chunks(fh):
        fh.seek(ele[0])#startat
        data=fh.read(ele[1])#endat
        print data

Ответ 10

Спасибо! Я недавно преобразовал в python 3 и был расстроен с помощью readlines (0) для чтения больших файлов. Это решило проблему. Но чтобы получить каждую строку, мне пришлось сделать еще пару шагов. Каждой строке предшествовал "b", который, я думаю, был в двоичном формате. Использование "decode (utf-8)" изменило его ascii.

Затем мне пришлось удалить "=\n" в середине каждой строки.

Затем я разделил строки на новой строке.

b_data=(fh.read(ele[1]))#endat This is one chunk of ascii data in binary format
        a_data=((binascii.b2a_qp(b_data)).decode('utf-8')) #Data chunk in 'split' ascii format
        data_chunk = (a_data.replace('=\n','').strip()) #Splitting characters removed
        data_list = data_chunk.split('\n')  #List containing lines in chunk
        #print(data_list,'\n')
        #time.sleep(1)
        for j in range(len(data_list)): #iterate through data_list to get each item 
            i += 1
            line_of_data = data_list[j]
            print(line_of_data)

Вот код, начинающийся чуть выше "print data" в коде Arohi.

Ответ 11

В этом другом вопросе я продемонстрировал метод параллельного байтового доступа с параллельным байтом:

Получение количества строк в текстовом файле без строк readline

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

Ответ 12

Heres код для загрузки текстовых файлов любого размера без возникновения проблем с памятью. Он поддерживает файлы размером в гигабайт

https://gist.github.com/iyvinjose/e6c1cb2821abd5f01fd1b9065cbc759d

загрузите файл data_loading_utils.py и импортируйте его в свой код.

использование

import data_loading_utils.py.py
file_name = 'file_name.ext'
CHUNK_SIZE = 1000000


def process_lines(data, eof, file_name):

    # check if end of file reached
    if not eof:
         # process data, data is one single line of the file

    else:
         # end of file reached

data_loading_utils.read_lines_from_file_as_data_chunks(file_name, chunk_size=CHUNK_SIZE, callback=self.process_lines)

Метод process_lines - это функция обратного вызова. Он будет вызываться для всех строк с данными параметров, представляющими одну строку файла за раз.

Вы можете настроить переменную CHUNK_SIZE в зависимости от конфигурации вашего оборудования.

Ответ 13

Это может быть полезно, если вы хотите работать параллельно и читать только фрагменты данных, но сохраняйте их чистыми с помощью новых строк.

def readInChunks(fileObj, chunkSize=1024):
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        while data[-1:] != '\n':
            data+=fileObj.read(1)
        yield data

Ответ 14

f=open('filename','r').read()
f1=f.split('\n')
for i in range (len(f1)):
    do_something_with(f1[i])

надеюсь, что это поможет.