Смешивание файлов и петель - PullRequest
27 голосов
/ 05 мая 2009

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

В любом случае, программа берет входной файл, анализирует его и создает выходной файл. Входной файл имеет определенный формат:

UI - 26474845
TI - the title (can be any number of lines)
AB - the abstract (can also be any number of lines)

Когда программа выдает ошибку, она дает вам справочную информацию, необходимую для отслеживания ошибки, а именно: пользовательский интерфейс, какой раздел (заголовок или аннотация) и номер строки относительно начала заголовка или аннотации. Я хочу записать оскорбительные предложения из входного файла с помощью функции, которая берет ссылочный номер и файл, находит предложение и записывает его в журнал. Лучший способ сделать это - продвигаться по файлу определенное количество раз (а именно, n раз, где n - номер строки относительно начала секунды). Казалось бы, есть смысл сделать это:

i = 1
while i <= lineNumber:
    print original.readline()
    i += 1

Я не понимаю, как это может привести к потере данных, но Python думает, что это произойдет, и говорит ValueError: Mixing iteration and read methods would lose data. Кто-нибудь знает, как это сделать правильно?

Ответы [ 4 ]

49 голосов
/ 05 мая 2009

Вы получаете ValueError, потому что ваш код, вероятно, имеет for line in original: в дополнение к original.readline(). Простое решение, которое решает проблему, не замедляя работу вашей программы и не занимая больше памяти, меняется

for line in original:
    ...

до

while True:
    line = original.readline()
    if not line: break
    ...
12 голосов
/ 05 мая 2009

Использовать for и перечислять .

Пример:

for line_num, line in enumerate(file):
    if line_num < cut_off:
        print line

ПРИМЕЧАНИЕ : Предполагается, что вы уже очищаете дескрипторы файлов и т. Д.

Кроме того, функция takewhile может оказаться полезной, если вы предпочитаете более функциональный вариант.

0 голосов
/ 02 февраля 2018

Вот версия без уродливого шаблона while True и без других модулей:

for line in iter(original.readline, ''):
    if …:   # to the beginning of the title or abstract
        for i in range(lineNumber):
            print original.readline(),
        break
0 голосов
/ 06 мая 2009

Если вам нужна только одна строка, это может помочь

import itertools

def getline(fobj, line_no):
    "Return a (1-based) line from a file object"
    return itertools.islice(fobj, line_no-1, line_no).next() # 1-based!

>>> print getline(open("/etc/passwd", "r"), 4)
'adm:x:3:4:adm:/var/adm:/bin/false\n'

Возможно, вы захотите перехватить ошибки StopIteration (если в файле меньше строк).

...