Как читать файл по строкам в Python?

В доисторические времена (Python 1.4) мы сделали:

fp = open('filename.txt') while 1: line = fp.readline() if not line: break print line 

после Python 2.1 мы сделали:

  • Отправить сообщение xmpp с использованием библиотеки python
  • Какой самый безопасный способ удаления файлов фреймворка Python, расположенных в разных местах, чем установка Brew
  • Ansi для UTF-8 с использованием ошибки python
  • Использование java-библиотеки из python
  • AttributeError: объект 'list' не имеет атрибута 'encode'
  • Закрепление неравных списков в python в список, который не отбрасывает ни один элемент из более длинного списка,
  •  for line in open('filename.txt').xreadlines(): print line 

    прежде чем мы получили удобный протокол итератора в Python 2.3 и могли бы сделать:

     for line in open('filename.txt'): print line 

    Я видел несколько примеров, используя более подробные:

     with open('filename.txt') as fp: for line in fp: print line 

    это предпочтительный метод, идущий вперед?

    [edit] Я понимаю, что оператор with обеспечивает закрытие файла … но почему это не включено в протокол итератора для файловых объектов?

  • Python Threading - нитки не запускаются
  • Поймать нажатой кнопку мыши из всплывающего меню qComboBox
  • Список расщепления Python на основе недостающих чисел в последовательности
  • Запись файла с определенными разрешениями в Python
  • ошибка компиляции в visual studio, связанная с python26
  • Python mechanize - две кнопки типа 'submit'
  • 4 Solutions collect form web for “Как читать файл по строкам в Python?”

    Существует только одна причина, по которой предпочтительнее:

     with open('filename.txt') as fp: for line in fp: print line 

    Мы все испорчены относительно детерминированной схемой подсчета CPython для сбора мусора. Другие гипотетические реализации Python не обязательно будут закрывать файл «достаточно быстро» без блока, если они используют какую-то другую схему для восстановления памяти.

    В такой реализации вы можете получить сообщение об ошибке «слишком много файлов» из ОС, если ваш код открывает файлы быстрее, чем сборщики мусора собирают финализаторы в сиротских файлах. Обычное обходное решение заключается в немедленном запуске GC, но это неприятный взлом, и это должно выполняться каждой функцией, которая может столкнуться с ошибкой, в том числе в библиотеках. Какой кошмар.

    Или вы можете просто использовать блок with блоком.

    Бонусный вопрос

    (Прекратите читать сейчас, если интересуетесь только объективными аспектами вопроса.)

    Почему это не включено в протокол итератора для файловых объектов?

    Это субъективный вопрос об дизайне API, поэтому у меня есть субъективный ответ в двух частях.

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

    Другие языки по существу пришли к одному и тому же выводу. Haskell кратко флиртовал с так называемым «ленивым IO», который позволяет вам перебирать файл и автоматически закрывать его, когда вы дойдете до конца потока, но в наши дни почти повсеместно не рекомендуется использовать ленивый IO в Haskell, а Haskell пользователи в основном перешли к более явному управлению ресурсами, например, Conduit, который ведет себя как блок with блоком в Python.

    На техническом уровне есть некоторые вещи, которые вы можете сделать с дескриптором файла в Python, который не будет работать, если итерация закрыла дескриптор файла. Например, предположим, что мне нужно дважды перебирать файл:

     with open('filename.txt') as fp: for line in fp: ... fp.seek(0) for line in fp: ... 

    Хотя это менее распространенный случай использования, рассмотрим тот факт, что я мог бы просто добавить три строки кода внизу к существующей базе кода, изначально имевшей три верхние строки. Если итерация закрыла файл, я бы не смог этого сделать. Таким образом, сохранение итераций и управление ресурсами отдельно упрощает компоновку фрагментов кода в более крупную рабочую программу Python.

    Композитоспособность – одна из важнейших особенностей использования языка или API.

    Да,

     with open('filename.txt') as fp: for line in fp: print line 

    это путь.

    Это не более подробный. Это безопаснее.

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

     def with_iter(iterable): with iterable as iter: for item in iter: yield item for line in with_iter(open('...')): ... 

    в Python 3.3, yield from оператора сделает это еще короче:

     def with_iter(iterable): with iterable as iter: yield from iter 
     f = open('test.txt','r') for line in f.xreadlines(): print line f.close() 
    Python - лучший язык программирования в мире.