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

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

Глава 8.8

8.8

Чтение:
read()

Метод возвращает содержимое файла одной строкой. Без аргумента — целиком, с числом — указанное количество символов. Ключ к пониманию всех методов чтения — позиция в файле: она сдвигается при каждом вызове и объясняет, почему повторный read() возвращает пустоту.

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

§1read() без аргумента

Вызов без аргументов возвращает всё содержимое файла как одну строку.

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

print(repr(content))
Вывододна строка с переводами внутри
'первая строка\nвторая строка\nтретья строка\n'

Результат — обычная строка со всеми свойствами из модуля 5: к ней применимы срезы, split(), find() и остальные методы.

§2Позиция в файле

У открытого файла есть позиция — место, откуда пойдёт следующее чтение. Сразу после открытия она равна нулю, а любое чтение её сдвигает.

main.pyпозиция до и после чтения
with open("demo.txt", encoding="utf-8") as file:
    print(file.tell())
    file.read(5)
    print(file.tell())
Выводпосле чтения пяти символов
0
10

Число 10 вместо ожидаемых 5 — не ошибка: tell() считает байты, а пять кириллических символов занимают в UTF-8 десять байт. Подробно об этом — глава 8.11.

§3Повторный вызов

Из механики позиции следует поведение, которое ставит в тупик каждого второго новичка.

main.pyвторой read() того же файла
with open("demo.txt", encoding="utf-8") as file:
    first = file.read()
    second = file.read()

print(len(first))
print(repr(second))
Выводвторой раз читать уже нечего
42
''
Файл читается один раз

После первого read() позиция стоит в конце, и всё последующее чтение возвращает пустоту. Ошибки при этом нет — программа спокойно работает с пустой строкой. Если содержимое нужно дважды, его сохраняют в переменную или возвращают позицию через seek(0).

§4read(size)

С аргументом метод читает не больше указанного числа символов и сдвигает позицию ровно на столько.

main.pyдва чтения по пять символов
with open("demo.txt", encoding="utf-8") as file:
    print(repr(file.read(5)))
    print(repr(file.read(5)))
Выводвторой вызов продолжил с места остановки
'перва'
'я стр'

Границы слов метод не учитывает — он отсчитывает символы. Если до конца файла осталось меньше запрошенного, вернётся столько, сколько есть.

§5Чтение порциями

Отсюда стандартный приём для больших файлов: читать блоками в цикле, пока не вернётся пустая строка.

main.pyобработка по десять символов
with open("demo.txt", encoding="utf-8") as file:
    while True:
        chunk = file.read(10)
        if not chunk:
            break
        print(repr(chunk))
Выводфайл прочитан кусками
'первая стр'
'ока\nвторая'
' строка\nтр'
'етья строк'
'а\n'

Проверка if not chunk опирается на истинность из главы 3.16: пустая строка ложна. Так файл любого размера обрабатывается при фиксированном расходе памяти.

§6Символы, а не байты

В текстовом режиме аргумент size задаётся в символах. Это важно для кириллицы, где символ занимает два байта.

Режимread(5) вернётtell() покажет
текстовый5 символовчисло байтов
двоичный "rb"5 байтовчисло байтов

Несовпадение единиц в одной строке таблицы — источник путаницы при работе с позицией, и глава 8.11 разбирает его отдельно.

§7Пустой файл и конец файла

Ни то ни другое ошибкой не считается — просто возвращается пустая строка.

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

with open("empty.txt", encoding="utf-8") as file:
    print(repr(file.read()))
Выводпустая строка вместо исключения
''

Пустая строка — универсальный признак «читать больше нечего». Именно на нём построен цикл из §5.

§8Переводы строк в результате

read() возвращает текст как есть, вместе с символами \n. Обычный print() их выведет как настоящие переносы, и структура станет незаметной.

main.pyтот же текст двумя способами
with open("demo.txt", encoding="utf-8") as file:
    content = file.read()

print(content)
print(repr(content))
Выводво втором случае видна структура
первая строка
вторая строка
третья строка

'первая строка\nвторая строка\nтретья строка\n'

Пустая строка после третьей — след завершающего \n. При отладке файлов repr() из главы 5.2 незаменим.

§9Разбить на строки

Если нужен список строк, прочитанное разбивают методом splitlines() из главы 5.10.

main.pyиз одной строки в список
with open("demo.txt", encoding="utf-8") as file:
    lines = file.read().splitlines()

print(lines)
Выводпереводы строк убраны
['первая строка', 'вторая строка', 'третья строка']

Именно splitlines(), а не split("\n"): последний оставил бы лишний пустой элемент из-за завершающего перевода. Есть и готовый метод readlines() — глава 8.10, — но он сохраняет символы \n.

§10Когда read() не подходит

Метод загружает файл в память целиком. Для файла в несколько гигабайт это означает несколько гигабайт оперативной памяти.

ЗадачаСпособ
небольшой файл целикомread()
файл любого размера, построчноперебор for line in file
файл любого размера, блокамиread(size) в цикле
первая строкаreadline()

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

main.pyперебор файла как коллекции
with open("demo.txt", encoding="utf-8") as file:
    for line in file:
        print(repr(line))
Выводстроки приходят с переводами
'первая строка\n'
'вторая строка\n'
'третья строка\n'

§11Двоичное чтение

В режиме "rb" метод возвращает bytes, а не строку.

main.pyпервые четыре байта
with open("demo.txt", "rb") as file:
    print(file.read(4))
Выводдва кириллических символа
b'\xd0\xbf\xd0\xb5'

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

§12Ошибки при чтении

СитуацияИсключение
файла нетFileNotFoundError
нет прав на чтениеPermissionError
файл открыт в режиме "w"UnsupportedOperation
двоичные данные в текстовом режимеUnicodeDecodeError
файл уже закрытValueError

Первые три наследуют от OSError из главы 8.3, четвёртая — от ValueError через UnicodeError. Значит, except OSError покроет проблемы доступа, но не проблемы кодировки — их ловят отдельно.

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

Что написаноЧто произойдётКак правильно
второй read() того же файлавернётся пустая строкасохранить результат или seek(0)
read() для файла в гигабайтывсё окажется в памятиперебор for line in file
file.read() после блока withValueError: файл закрытчитать внутри блока
read().split("\n")лишний пустой элемент в концеsplitlines()
ждать read(5) ровно пять байтв текстовом режиме это символыдля байтов — режим "rb"
читать двоичный файл без "b"UnicodeDecodeErrorрежим "rb"
ждать исключение в конце файлавернётся пустая строкапроверять if not chunk

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

Почему второй read() возвращает пустую строку?

После первого чтения позиция стоит в конце файла. Ошибки нет — просто читать больше нечего.

В чём измеряется аргумент read(size)?

В текстовом режиме — в символах, в двоичном — в байтах. При этом tell() всегда показывает байты.

Как понять, что файл закончился?

По пустой строке в результате. Исключения при достижении конца не возникает.

Почему splitlines() лучше, чем split("\n")?

Файлы обычно заканчиваются переводом строки, и split() добавил бы лишний пустой элемент.

Когда read() использовать не стоит?

Когда файл большой: метод загружает его в память целиком. Для таких случаев есть построчный перебор и чтение блоками.

Что вернёт read() в режиме "rb"?

Объект bytes, а не строку. Кодировка при этом не применяется.

§15Шпаргалка

Всё содержимоеtext = file.read()
Порцияchunk = file.read(1024)
Список строкfile.read().splitlines()
Построчноfor line in file:
Вернуться в началоfile.seek(0)
Конец файлаif not chunk: break

Итог главы

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

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