2009-03-03 6 views
2

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

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
данные
данные б
данные гр
\ N
Запись 2
данные А
данных B
данные с
\ п
\ п

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

Запись 1
данные
данные б
данные с
\ n
Запись 2
данные a
данные б
данные с
\ п

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

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

Спасибо.

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

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

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

ответ

6

То, как это написано сейчас, вероятно, не работает; с 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 

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

+0

Вы правильно поняли, и я редактировал свой пост, чтобы быть более четким, чем я хочу. Ваш подход очень хорош и решает мою проблему, большое спасибо, но, все же, почему Python не читает последнюю строку, когда она пуста? –

0

line.strip() приведет к пустой строке на пустой строке. Пустая строка значение False, так что вы глотать пустую строку

>>> bool("\n".strip()) 
False 
>>> bool("\n") 
True 
0

Если вы звоните 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'] 
5

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

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 была дорогостоящей или имела побочные эффекты, которые не должны происходить, если строка пуста.

EDIT: Я оставлю свой ответ здесь ради потомков, но DNS ниже получил первоначальное намерение правильно, где несколько строк вносят вклад в ту же запись SomeObject(), которую я полностью замаскировал.

+0

Ваш код соответствует коду автора, но из формулировки его вопроса и его выборочных данных не похоже, что он хочет создать новый SomeObject на каждой непустой строке. Он хочет, чтобы блок строк вносил вклад в один объект SomeObject. – DNS

+0

Ах да, вы правы. –

+0

Отредактировано мое сообщение, чтобы обратиться к вашей, DNS. –

0

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

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

+0

Я не могу прочитать весь файл в памяти, это + 100k строк. –

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