Python: itertools.islice не работает в цикле - PullRequest
2 голосов
/ 16 февраля 2011

У меня есть такой код:

#opened file f
goto_line = num_lines #Total number of lines
while not found:
   line_str = next(itertools.islice(f, goto_line - 1, goto_line))
   goto_line = goto_line/2
   #checks for data, sets found to True if needed

line_str является правильным первым проходом, но каждый проход после этого читает другую строку, чем должно.

Так, например, goto_lineначинается как 1000. Он читает строку 1000 просто отлично.Затем следующий цикл goto_line равен 500, но он не читает строку 500. Он читает строку ближе к 1000.

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

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

Ответы [ 2 ]

5 голосов
/ 16 февраля 2011

Итераторы Python могут использоваться только один раз.Это легче всего увидеть на примере.Следующий код

from itertools import islice
a = range(10)
i = iter(a)
print list(islice(i, 1, 3))
print list(islice(i, 1, 3))
print list(islice(i, 1, 3))
print list(islice(i, 1, 3))

печатает

[1, 2]
[4, 5]
[7, 8]
[]

Нарезка всегда начинается там, где мы остановились в прошлый раз.

Самый простой способ заставить ваш код работать, это использоватьf.readlines(), чтобы получить список строк в файле и затем использовать обычную нарезку списка Python [i:j].Если вы действительно хотите использовать islice(), вы можете начать чтение файла с самого начала каждый раз, используя f.seek(0), но это будет очень неэффективно.

0 голосов
/ 16 февраля 2011

Вы не можете (таким образом - возможно, есть какой-то способ, в зависимости от того, как файл открыт) вернуться в файл.Стандартный файловый итератор (фактически большинство итераторов - протокол итераторов Python поддерживает только итераторы вперед) перемещает only вперед.Таким образом, после чтения k строк, чтение других k/2 строк фактически дает k+k/2 -ую строку.

Вы могли бы попробовать прочитать весь файл в память, но у вас многоданных, поэтому потребление памяти, вероятно, становится проблемой.Вы можете использовать file.seek для прокрутки файла.Но это еще много работы - может быть, вы могли бы использовать файл с отображением в памяти ?Это возможно, только если строки имеют фиксированный размер.Если это необходимо, вы можете предварительно рассчитать номера строк, которые вы хотите проверить, и сохранить все эти строки (не должно быть слишком много, примерно int(log_2(line_count)) + 1, если я не ошибаюсь) за одну итерацию, чтобы вы не делали этого.после прочтения всего файла нужно прокрутить назад.

...