Как да прочетете голям файл ред по ред

Искам да итерирам по всеки ред от цял файл. Един от начините за това е да прочетете целия файл, да го запишете в списък и след това да преминете през интересуващия ви ред. Този метод използва много памет, затова търся алтернатива.

Моят код досега:

for each_line in fileinput.input(input_file):
    do_something(each_line)

    for each_line_again in fileinput.input(input_file):
        do_something(each_line_again)

Изпълнението на този код дава съобщение за грешка: устройството е активно.

Някакви предложения?

Целта е да се изчисли двойно сходство на низове, което означава, че за всеки ред във файла искам да изчисля разстоянието на Левенщайн с всеки друг ред.

Два начина за ефективно използване на паметта в подреден ред (първият е най-добрият) -

  1. използване на with - поддържа се от Python 2.5 и нагоре
  2. използване на yield, ако наистина искате да имате контрол върху това колко да се чете

1. използване на with

with е хубавият и ефективен питонски начин за четене на големи файлове. предимства - 1) файловият обект се затваря автоматично след излизане от блока за изпълнение на with. 2) обработка на изключения вътре в блока with. 3) цикълът на паметта for итерира през файловия обект f ред по ред. вътрешно се извършва буфериран IO (за оптимизиране на скъпите IO операции) и управление на паметта.

with open("x.txt") as f:
    for line in f:
        do something with data

2. използване на yield

Понякога може да се иска по-прецизен контрол върху това колко да се чете при всяка итерация. В този случай използвайте iter & yield. Имайте предвид, че при този метод е необходимо изрично да затворите файла в края.

def readInChunks(fileObj, chunkSize=2048):
    """
    Lazy function to read a file piece by piece.
    Default chunk size: 2kB.
    """
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        yield data

f = open('bigFile')
for chuck in readInChunks(f):
    do_something(chunk)
f.close()

Примери и за пълнота - методите по-долу не са толкова добри или не са толкова елегантни за четене на големи файлове, но моля, прочетете, за да получите закръглено разбиране.

В Python най-разпространеният начин за четене на редове от файл е да се направи следното:

for line in open('myfile','r').readlines():
    do_something(line)

Когато това се прави, обаче, функцията readlines() (същото важи и за функцията read()) зарежда целия файл в паметта, след което го итерира. Малко по-добър подход (първите два споменати метода са най-добри) за големи файлове е да се използва модулът fileinput, както следва:

import fileinput

for line in fileinput.input(['myfile']):
    do_something(line)

извикването на fileinput.input() чете последователно редове, но не ги'запазва в паметта, след като са'прочетени или дори просто така това, тъй като file в питон е итерируем.

Референции

  1. Python with statement
Коментари (7)

Това е възможен начин за четене на файл в питон:

f = open(input_file)
for line in f:
    do_stuff(line)
f.close()

той не разпределя пълен списък. Той итерира по редовете.

Коментари (2)

От документацията на python за fileinput.input():

Това итерира над редовете на всички файлове, изброени в sys.argv[1:], като по подразбиране се използва sys.stdin, ако списъкът е празен

по-нататък дефиницията на функцията е:

fileinput.FileInput([files[, inplace[, backup[, mode[, openhook]]]]])

Четейки между редовете, това ми подсказва, че файловете могат да бъдат списък, така че бихте могли да получите нещо като:

for each_line in fileinput.input([input_file, input_file]):
  do_something(each_line)

Вижте тук за повече информация

Коментари (0)