2013-07-28 2 views
0

Я читаю в файл с помощьюПропустить обратно в файл в Python

for line in fin: 
    process(line) 

Однако, я иногда, как пропустить назад некоторые строки в файл и просто вести оттуда. Я не буду знать количество строк заранее, так как это зависит от вычислений в коде. Поэтому я хотел бы, чтобы это было что-то вроде

for line in fin: 
    x = process(line) 
    if (x == 23): 
     skip back xxx lines and continue 

Как вы можете это сделать в python?

Это что-то, что можно сделать с помощью mmap, например? Файл большой, поэтому я не хочу просто хранить все это в памяти.

+0

Насколько велика? Если вы разработали формат файла, подумайте об изменении его, чтобы он легко анализировался в одном прокрутке вперед. –

+0

Просто замечание на ваш код здесь: 'для строки в fin.readlines()' перебирает список строк в вашей памяти. 'for line in fin ', однако, будет читать строку из файла, затем читать другую и т. д. – sjakobi

+0

@simon О, дорогая. Благодаря! –

ответ

0

Другой подход:

In [11]: from collections import deque 

In [12]: cache = deque(maxlen=max_skip_back) 

In [13]: for line in fin: 
    ....:  line = line.strip() 
    ....:  cache.append(line) 
    ....:  x = process(line) 
    ....:  if x == 23: 
    ....:   for line in cache[-this_skip_back:]: 
    ....:    process(line) 

Это не будет читать весь файл в память. deques отбрасывают свои первые элементы, если они дольше, чем maxlen.

+0

Это может сработать, если я смогу угадать максимум, который мне когда-либо понадобится, чтобы пропустить назад. –

+0

@felix: отредактировал мой ответ, чтобы разрешить переменное количество строк, которые вы пропустите назад. – sjakobi

1

Try что-то вроде

lines = fin.readlines() 
i = 0 
while i < len(lines): 
    x = process(lines[i]) 
    if x == 23: 
     i -= num_lines 
    else: 
     i += 1 
+0

Может превратить это if-else в тройной? – Basic

+3

@Basic 'i + = -num_lines if x == 23 else 1' выглядит далеко уродливым – SheetJS

+1

@Nirk Я бы не согласился, но тогда это вопрос предпочтения – Basic

1

Я бы предложил записать позицию каждой строки в массиве, когда вы идете, используя метод tell() для файлового объекта. Это обеспечивает смещение местоположения каждой линии по мере ее возникновения. Затем, когда вы хотите пропустить назад, вы используете f.seek() для перехода назад в указанные местоположения.

Например:

linestarts = [] 
f = open(myfile,"r") 
... 
linestarts.append(f.tell()) # save each line 
f.readline() # do stuff reading a line 
... 
# want to jump back 3 lines for some reason 
f.seek(linestarts[-3]) 

Конечно, другой вариант заключается в кэш последние несколько строк в своем коде, но это то, что STDIO это уже делает для вас.

+0

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

+0

Это здорово, спасибо. Недостатком является то, что linestarts растет с размером файла, я полагаю, поэтому объем пространства, который вы сохраняете, просто хранит строки, может отличаться. Возможно, вы могли бы сделать linestarts в dequeue, если бы знали максимальное количество строк, которые вы когда-либо пропустили. –

Смежные вопросы