Искам да итерирам по всеки ред от цял файл. Един от начините за това е да прочетете целия файл, да го запишете в списък и след това да преминете през интересуващия ви ред. Този метод използва много памет, затова търся алтернатива.
Моят код досега:
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)
Изпълнението на този код дава съобщение за грешка: устройството е активно
.
Някакви предложения?
Целта е да се изчисли двойно сходство на низове, което означава, че за всеки ред във файла искам да изчисля разстоянието на Левенщайн с всеки друг ред.
Два начина за ефективно използване на паметта в подреден ред (първият е най-добрият) -
with
- поддържа се от Python 2.5 и нагореyield
, ако наистина искате да имате контрол върху това колко да се чете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
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
в питон е итерируем.
Това е възможен начин за четене на файл в питон:
f = open(input_file)
for line in f:
do_stuff(line)
f.close()
той не разпределя пълен списък. Той итерира по редовете.
От документацията на 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)
Вижте тук за повече информация