2014-06-19 7 views
5

normalnie uniknąć odczytywania plików tak:Memory-skuteczny sposób iteracyjne nad częścią dużego pliku

with open(file) as f: 
    list_of_lines = f.readlines() 

i korzystać z tego typu kodu zamiast.

f = open(file) 
for line in file: 
    #do something 

Chyba mam tylko do iteracji przez kilka wierszy w pliku (i wiem, które linie te są), to myślę, że jest łatwiejsza do podjęcia Plastry list_of_lines. Teraz to wróciło, by mnie ugryźć. Mam plik OGROMNY (odczytanie go do pamięci nie jest możliwe), ale nie muszę powtarzać we wszystkich wierszach tylko kilku z nich. Mam kod zakończony, który znajduje się w miejscu, w którym znajduje się moja pierwsza linia i znajduje się, ile kolejnych linii muszę edytować. Po prostu nie mam pomysłu na pisanie tej pętli.

n = #grep for number of lines 
start = #pattern match the start line 
f=open('big_file') 
#some loop over f from start o start + n 
     #edit lines 

EDYCJA: mój tytuł mógł prowadzić do debaty, a nie odpowiedzi.

+0

co masz na myśli przez "#edit lines", zrobić coś z liniami takimi jak przechowywanie ich na liście lub zapisywanie ich do innego pliku lub modyfikowanie tych linii w dużym pliku? – timgeb

+0

W jaki sposób znajdujesz pierwszy wiersz, a po nim liczbę linii, które chcesz edytować? Musisz to przeczytać od początku, prawda? – dano

+0

Zamierzam edytować linie w pliku, a następnie drukować rzecz przed i po typie w osobnym pliku. Będę drukował tylko linie, które zmienię, na inny plik. – Ajay

Odpowiedz

12

Jeśli dobrze rozumiem twoje pytanie, napotkany problem polega na tym, że przechowuje się linie tekstu na liście, a następnie wykonanie wycinka zajmuje zbyt dużo pamięci. To, czego chcesz, to odczytać plik wiersz po wierszu, ignorując wszystkie oprócz określonego zestawu linii (np. Linie [17,34) na przykład).

Spróbuj użyć numeru enumerate, aby śledzić numer linii, na której się znajdujesz podczas przeglądania pliku. Oto podejście generator oparty na który wykorzystuje yield do wyjścia ciekawych wierszy tylko jeden na raz:

def read_only_lines(f, start, finish): 
    for ii,line in enumerate(f): 
     if ii>=start and ii<finish: 
      yield line 
     elif ii>=finish: 
      return 

f = open("big text file.txt", "r") 
for line in read_only_lines(f, 17, 34): 
    print line 

Ten read_only_lines funkcja zasadzie reimplements itertools.islice z biblioteki standardowej, więc można używać, aby uczynić jeszcze bardziej kompaktowy realizacja:

from itertools import islice 
for line in islice(f, 17, 34): 
    print line 

Jeśli chcesz uchwycić kierunki zainteresowania listy zamiast generatora, po prostu rzucić je z listy:

from itertools import islice 
lines_of_interest = list(islice(f, 17, 34)) 

do_something_awesome(lines_of_interest) 
do_something_else(lines_of_interest) 
+2

drobny problem - read_only_lines() odczytuje cały plik, nawet gdy minęło już koniec, przerwa byłaby przyjemna – tdelaney

+1

Dobra rada, @tdelaney Naprawiono to tak, aby generator powrócił w tym momencie. –

+0

@Dan Dodałem twoją odpowiedź do mojego kodu, i to działa wspaniale.Dziękuję, że nie spotkałem 'wyliczyć()' zanim bardzo użyteczne.Dziękuję! – Ajay

Powiązane problemy