Модуль 8 · Исключения и файлы

Справочник по Python · модуль 8 · исключения и файлы

Глава 8.10

8.10

Чтение:
readlines()

Метод возвращает список всех строк файла — каждую вместе с завершающим переводом строки. Это удобно, когда нужен именно список: с индексами, сортировкой и повторными проходами. Плата — весь файл оказывается в памяти.

Категория
Файлы
Уровень
Базовый
Связанные темы
Списки, строки, память
Зачем это знать
Получить строки файла как обычный список

§1Список строк

readlines() читает файл до конца и возвращает список, в котором каждый элемент — одна строка.

main.pyфайл из трёх строк
with open("demo.txt", encoding="utf-8") as file:
    lines = file.readlines()

print(lines)
print(len(lines))
Выводобычный список из главы 3.1
['первая строка\n', 'вторая строка\n', 'третья строка\n']
3

Дальше это самый обычный список: доступен по индексу, поддерживает срезы, сортировку и всё остальное из модуля 3.

§2Переводы строк сохраняются

Как и readline(), метод оставляет \n в конце каждого элемента. Это регулярно портит сравнения.

main.pyсравнение с ожидаемым текстом
with open("demo.txt", encoding="utf-8") as file:
    lines = file.readlines()

print(lines[0] == "первая строка")
print(lines[0].strip() == "первая строка")
Выводбез очистки совпадения нет
False
True

§3Убрать переводы

Есть два способа получить список без \n, и второй короче.

main.pyвключение и splitlines()
with open("demo.txt", encoding="utf-8") as file:
    first = [line.strip() for line in file.readlines()]

with open("demo.txt", encoding="utf-8") as file:
    second = file.read().splitlines()

print(first)
print(second)
Выводрезультаты совпали
['первая строка', 'вторая строка', 'третья строка']
['первая строка', 'вторая строка', 'третья строка']

Разница есть в деталях: strip() из главы 5.9 убирает и пробелы по краям, а splitlines() из главы 5.10 — только переводы строк. Если ведущие пробелы значимы, подходит второй способ.

§4Зачем нужен список

Построчный перебор из главы 8.9 экономнее, но список умеет то, чего перебор не может.

main.pyобращение по индексу и с конца
with open("demo.txt", encoding="utf-8") as file:
    lines = file.readlines()

print(lines[0].strip())
print(lines[-1].strip())
print(len(lines))
Выводпервая, последняя и количество
первая строка
третья строка
3
НужноСписок подходит
количество строкlen(lines)
последняя строкаlines[-1]
пройти файл дваждыда, список не «кончается»
отсортировать строкиsorted(lines)
смотреть на соседние строкиlines[i] и lines[i + 1]

Последняя строка таблицы — приём из главы 3.6: сравнение соседей требует доступа по индексу, а при построчном переборе предыдущая строка уже потеряна.

§5Аргумент sizehint

Необязательный аргумент ограничивает объём чтения — но работает не так, как можно подумать.

main.pyограничение в десять символов
with open("demo.txt", encoding="utf-8") as file:
    print(file.readlines(10))
Выводстрока вернулась целиком, хотя она длиннее
['первая строка\n']

Обратите внимание: в строке тринадцать символов, а лимит был десять. Метод не обрезает строки — он только решает, читать ли следующую.

§6Как работает sizehint

  1. Метод читает очередную строку целиком.
  2. Складывает её длину с уже прочитанным.
  3. Если сумма достигла sizehint — останавливается.
  4. Иначе читает следующую строку.

Отсюда и название: это подсказка (hint), а не жёсткая граница. Даже readlines(1) вернёт одну целую строку — метод никогда не отдаёт обрезанные строки.

main.pyминимально возможный лимит
with open("demo.txt", encoding="utf-8") as file:
    print(file.readlines(1))
Выводвсё равно целая строка
['первая строка\n']

Этим sizehint отличается от size у read() и readline(): те обрезают ровно по счёту.

§7Пустой файл

Для пустого файла метод возвращает пустой список — не None и не ошибку.

main.pyфайл без содержимого
with open("empty.txt", "w", encoding="utf-8"):
    pass

with open("empty.txt", encoding="utf-8") as file:
    print(file.readlines())
Выводпустой список
[]

Цикл по такому списку просто не выполнится ни разу — проверять отдельно обычно не требуется.

§8Позиция после чтения

readlines() дочитывает файл до конца, поэтому позиция оказывается в конце — со всеми последствиями из главы 8.8.

main.pyвторой вызов
with open("demo.txt", encoding="utf-8") as file:
    first = file.readlines()
    second = file.readlines()

print(len(first), len(second))
Выводво второй раз читать нечего
3 0

Впрочем, повторное чтение здесь и не нужно: полученный список можно перебирать сколько угодно раз — в этом и смысл.

§9Пара с writelines()

Теперь становится понятно, почему writelines() из главы 8.7 не добавляет переводы строк: два метода образуют пару.

main.pyпрочитали и записали обратно
with open("demo.txt", encoding="utf-8") as source:
    lines = source.readlines()

with open("copy.txt", "w", encoding="utf-8") as target:
    target.writelines(lines)

print(open("copy.txt", encoding="utf-8").read() == open("demo.txt", encoding="utf-8").read())
Выводфайл воспроизведён точь-в-точь
True

Переводы строк уже внутри элементов — добавь их writelines() сам, копия получилась бы с двойными интервалами.

§10readlines() или перебор

Главный недостаток — память: список держит весь файл целиком, да ещё и с накладными расходами на сам список.

readlines()for line in file
памятьвесь файлодна строка
доступ по индексуестьнет
повторный проходестьнет
len()естьнет
файл в гигабайтыопаснобезопасно

Правило: если нужен именно список — брать readlines(). Если нужно просто пройти по строкам — перебор.

§11Три способа получить строки

Сравнениеодна задача, три записи
file.readlines()              список строк С переводами
file.read().splitlines()      список строк БЕЗ переводов
for line in file:             по одной, с переводами

Первые два одинаково расходуют память — оба читают файл целиком. Выбор между ними определяется только тем, нужны ли символы \n в элементах.

§12Частые ошибки

Что написаноЧто произойдётКак правильно
lines[0] == "текст"False из-за \n в концеlines[0].strip() == "текст"
readlines() для файла в гигабайтывесь файл окажется в памятиfor line in file
ждать от readlines(10) ровно десять символовстроки не обрезаютсяэто подсказка, а не лимит
второй readlines() того же файлавернётся пустой списокперебирать полученный список
readlines() после блока withValueError: файл закрытчитать внутри блока
print(lines) для показа пользователювыведется список с \n и кавычкамиprint("".join(lines))

§13Проверьте себя

Что возвращает readlines()?

Список строк файла, каждая — вместе с завершающим переводом строки.

Как получить список без \n?

file.read().splitlines() или включение со strip() по результату readlines().

Обрежет ли readlines(10) длинную строку?

Нет. Метод дочитывает строку целиком и только потом решает, читать ли следующую. Это подсказка, а не жёсткая граница.

Почему writelines() не добавляет переводы строк?

Он парный к readlines(), который их сохраняет. Иначе при обратной записи переводов стало бы вдвое больше.

Когда readlines() предпочтительнее перебора?

Когда нужен именно список: доступ по индексу, длина, сортировка, сравнение соседних строк или повторный проход.

Что вернёт метод для пустого файла?

Пустой список []. Ни ошибки, ни None.

§14Шпаргалка

Список строкlines = file.readlines()
Без переводовfile.read().splitlines()
Количествоlen(lines)
Последняяlines[-1].strip()
Записать обратноtarget.writelines(lines)
Большой файлfor line in file:

Итог главы

readlines() возвращает список всех строк файла вместе с переводами — и потому образует пару с writelines(), позволяя воспроизвести файл точь-в-точь. Список даёт то, чего не даёт построчный перебор: длину, индексы, сортировку и повторные проходы. Аргумент sizehint ограничивает объём, но строки не обрезает — это подсказка, а не лимит. Цена всего этого — весь файл в памяти, поэтому для больших файлов остаётся перебор.

Глава 8.10 · Чтение: readlines() · Справочник по Python Автор: Макаров Максим Николаевич