Справочник по Python · модуль 8 · исключения и файлы
Глава 8.10
Чтение:
readlines()
Метод возвращает список всех строк файла — каждую вместе с завершающим переводом строки. Это удобно, когда нужен именно список: с индексами, сортировкой и повторными проходами. Плата — весь файл оказывается в памяти.
- Категория
- Файлы
- Уровень
- Базовый
- Связанные темы
- Списки, строки, память
- Зачем это знать
- Получить строки файла как обычный список
§1Список строк
readlines() читает файл до конца и возвращает список, в котором каждый элемент — одна строка.
with open("demo.txt", encoding="utf-8") as file: lines = file.readlines() print(lines) print(len(lines))
['первая строка\n', 'вторая строка\n', 'третья строка\n'] 3
Дальше это самый обычный список: доступен по индексу, поддерживает срезы, сортировку и всё остальное из модуля 3.
§2Переводы строк сохраняются
Как и readline(), метод оставляет \n в конце каждого элемента. Это регулярно портит сравнения.
with open("demo.txt", encoding="utf-8") as file: lines = file.readlines() print(lines[0] == "первая строка") print(lines[0].strip() == "первая строка")
False True
§3Убрать переводы
Есть два способа получить список без \n, и второй короче.
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 экономнее, но список умеет то, чего перебор не может.
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
Необязательный аргумент ограничивает объём чтения — но работает не так, как можно подумать.
with open("demo.txt", encoding="utf-8") as file: print(file.readlines(10))
['первая строка\n']
Обратите внимание: в строке тринадцать символов, а лимит был десять. Метод не обрезает строки — он только решает, читать ли следующую.
§6Как работает sizehint
- Метод читает очередную строку целиком.
- Складывает её длину с уже прочитанным.
- Если сумма достигла
sizehint— останавливается. - Иначе читает следующую строку.
Отсюда и название: это подсказка (hint), а не жёсткая граница. Даже readlines(1) вернёт одну целую строку — метод никогда не отдаёт обрезанные строки.
with open("demo.txt", encoding="utf-8") as file: print(file.readlines(1))
['первая строка\n']
Этим sizehint отличается от size у read() и readline(): те обрезают ровно по счёту.
§7Пустой файл
Для пустого файла метод возвращает пустой список — не None и не ошибку.
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.
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 не добавляет переводы строк: два метода образуют пару.
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() после блока with | ValueError: файл закрыт | читать внутри блока |
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 ограничивает объём, но строки не обрезает — это подсказка, а не лимит. Цена всего этого — весь файл в памяти, поэтому для больших файлов остаётся перебор.