Сохранение последней новой строки при чтении файла - PullRequest
2 голосов
/ 03 марта 2009

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

def fread():
    record = False
    for line in open('somefile.txt'):
        if line.startswith('Record'):
            record = True
            d = SomeObject()

        # do some processing with line
        d.process(line)

        if not line.strip() and record:
            yield d
            record = False

for record in fread():
    print(record)

В этом примере данных все работает как положено ('---' - пустая строка):

Запись 1
данные
данные b
данные с
\ П
Запись 2
данные
данные b
данные с
\ П
\ П

Но при этом последняя запись не возвращается:

Запись 1
данные
данные b
данные с
\ П
Запись 2
данные
данные b
данные с
\ n

Как сохранить последнюю новую строку из файла, чтобы получить последнюю запись?

PS .: Я использую термин «консервировать», так как не смог найти лучшего названия.

Спасибо.

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

Еще немного объяснений: объект SomeObject создается для каждой записи в файле, и записи разделяются пустыми новыми строками. В конце записи он возвращает объект, чтобы я мог его использовать (сохранить в БД, сравнить с другими объектами и т. Д.).

Основная проблема, когда файл заканчивается одной новой строкой, последняя запись не возвращается. Кажется, что Python не читает последнюю строку, когда она пуста.

Ответы [ 5 ]

6 голосов
/ 03 марта 2009

Способ написания сейчас, вероятно, не работает; с d = SomeObject() внутри вашего цикла, новый SomeObject создается для каждой строки. Тем не менее, если я правильно понимаю, вы хотите, чтобы все строки между пустыми строками вносили вклад в этот один объект. Вместо этого вы можете сделать что-то вроде этого:

def fread():
    d = None
    for line in open('somefile.txt'):

        if d is None:
            d = SomeObject()

        if line.strip():
            # do some processing
        else:
            yield d
            d = None

    if d: yield d

Это не очень хороший код, но он работает; последний объект, который пропускает свою пустую строку, возвращается после завершения цикла.

5 голосов
/ 03 марта 2009

Вы можете найти небольшой поворот в более классически питоническом направлении, улучшающий предсказуемость кода:

def fread():
    for line in open('text.txt'):
        if line.strip():
            d = SomeObject()
            yield d

    raise StopIteration

for record in fread():
    print record

Предпочтительный способ завершить работу генератора в Python, хотя часто это не является строго необходимым, - за исключением StopIteration. Использование if line.strip() просто означает, что вы сделаете выход, если после удаления пробела останется что-нибудь в строке. Конструкция SomeObject () может быть где угодно ... Я просто случайно переместил его, если конструкция SomeObject была дорогой или имела побочные эффекты, которых не должно быть, если строка пуста.

РЕДАКТИРОВАТЬ: я оставлю здесь свой ответ для потомков, но нижеприведенный DNS правильно понял намерение, где несколько строк вносят вклад в одну и ту же запись SomeObject () (которую я полностью замаскировал).

0 голосов
/ 03 марта 2009

замените open('somefile.txt'): на open('somefile.txt').read().split('\n'):, и ваш код будет работать.

Но ответ Джаррет Харди лучше.

0 голосов
/ 03 марта 2009

Если вы повторно вызываете readline (в цикле) для своего файлового объекта (вместо использования in), он должен работать так, как вы ожидаете. Сравните их:

>>> x = open('/tmp/xyz')
>>> x.readline()
'x\n'
>>> x.readline()
'\n'
>>> x.readline()
'y\n'
>>> x.readline()
''
>>> open('/tmp/xyz').readlines()
['x\n', '\n', 'y\n']
0 голосов
/ 03 марта 2009

line.strip () приведет к пустой строке в пустой строке. Пустая строка - False, поэтому вы глотаете пустую строку

>>> bool("\n".strip())
False
>>> bool("\n")
True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...