Python: уроки, справочник и задачи

Чтение и запись файлов в Python 3

Раздел: Работа с файлами в Python · Обновлено 31.10.2026

Чтение и запись файлов в Python сводятся к трем шагам: открыть файл функцией open(), вызвать методы чтения или записи и закрыть файл. Ниже разобраны все способы прочитать текст (целиком, по строкам, в список), записать и дописать данные, выбрать режим и кодировку, а также работа с байтами и позицией в файле.

Чтение и запись файлов в Python 3
Фото: Jin Zan / CC BY-SA 3.0, Wikimedia Commons
Содержание статьи
  1. Режимы открытия для чтения и записи
  2. Чтение файла
    1. Метод read()
    2. Методы readline() и readlines()
    3. Перебор строк в цикле for
  3. Запись в файл
    1. Методы write() и writelines()
    2. Функция print() с параметром file
    3. Дозапись в конец файла
  4. Кодировка и переносы строк
  5. Бинарные файлы и позиция в файле
  6. Короткий путь через pathlib
  7. Методы файлового объекта
  8. Частые вопросы
    1. Почему после записи файл пустой?
    2. Как прочитать файл в список без символов переноса?
    3. Как записать в файл число или список?
    4. Чем режим a отличается от w?
    5. Что делать при ошибке UnicodeDecodeError?

Режимы открытия для чтения и записи

Что можно делать с файлом, определяет второй аргумент open(). Ошибка в режиме дает либо исключение, либо, что хуже, молча стертый файл. Подробно сама функция и закрытие файла разобраны в статье про открытие и закрытие файла, здесь собрана шпаргалка.

РежимЧто делаетЕсли файла нетЕсли файл есть
rЧтение (по умолчанию)FileNotFoundErrorЧитает с начала
wЗаписьСоздаетОчищает содержимое
aДозапись в конецСоздаетПишет после старых данных
xТолько созданиеСоздаетFileExistsError
r+Чтение и записьFileNotFoundErrorНе очищает

К любому режиму можно добавить b (байты, например rb) или t (текст, используется по умолчанию). Все примеры ниже используют конструкцию with: она закрывает файл сама, даже если внутри блока произошла ошибка.

Чтение файла

Пусть рядом со скриптом лежит файл notes.txt из трех строк. Прочитать его можно четырьмя способами, и выбор зависит от размера файла и того, что нужно сделать с текстом.

Метод read()

read() без аргументов возвращает все содержимое одной строкой. С числовым аргументом читает не больше указанного количества символов (в бинарном режиме байтов), и следующий вызов продолжает с того места, где остановился предыдущий.

with open('notes.txt', encoding='utf-8') as f:
    first = f.read(3)    # первые 3 символа
    rest = f.read()      # все остальное
print(first)
print(rest)

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

Методы readline() и readlines()

readline() читает одну строку вместе с символом переноса \n в конце. readlines() возвращает список всех строк, и в каждом элементе тоже остается перенос.

with open('notes.txt', encoding='utf-8') as f:
    header = f.readline()
    other = f.readlines()
print(repr(header))   # 'Первая строка\n'
print(other)          # ['Вторая строка\n', 'Третья строка\n']

Если переносы не нужны, используйте f.read().splitlines(): метод вернет список строк уже без \n.

Перебор строк в цикле for

Файловый объект сам является итератором по строкам. Цикл for читает файл порциями, поэтому подходит для файлов любого размера, в том числе логов в несколько гигабайт. Приемы для очень больших файлов собраны в статье о чтении больших файлов.

with open('notes.txt', encoding='utf-8') as f:
    for number, line in enumerate(f, start=1):
        print(number, line.rstrip('\n'))

Запись в файл

Для записи файл открывают в режиме w, a или x. Попытка вызвать write() у файла, открытого на чтение, вызовет исключение io.UnsupportedOperation.

Методы write() и writelines()

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

lines = ['яблоко', 'груша', 'слива']
with open('fruits.txt', 'w', encoding='utf-8') as f:
    f.write('Список фруктов\n')
    f.writelines(item + '\n' for item in lines)

Записать можно только строку. Число или список сначала преобразуют: f.write(str(42)). Для словарей и списков удобнее формат JSON, о нем рассказано в материале про запись и чтение JSON-файлов.

Функция print() с параметром file

Если хочется, чтобы переносы и пробелы между значениями расставлялись сами, передайте файл в print(). Функция сама преобразует аргументы в строки.

with open('report.txt', 'w', encoding='utf-8') as f:
    print('Итого:', 150, 'руб.', file=f)
    print('Позиций:', 3, file=f)

Дозапись в конец файла

Режим w стирает старое содержимое сразу при открытии, даже если вы ничего не запишете. Чтобы добавить строки к существующему файлу, например к логу, используйте режим a.

from datetime import datetime

with open('app.log', 'a', encoding='utf-8') as log:
    log.write(f'{datetime.now():%Y-%m-%d %H:%M} запуск\n')

Кодировка и переносы строк

Если не указать encoding, Python берет кодировку из настроек системы. В версиях до 3.15 на Windows это обычно cp1251, на Linux и macOS UTF-8, поэтому файл с русским текстом, записанный на одном компьютере, может прочитаться кракозябрами на другом. Указывайте encoding='utf-8' явно и при чтении, и при записи.

Если в файле встречаются битые байты, параметр errors задает реакцию: 'strict' (исключение, по умолчанию), 'ignore' (пропустить) или 'replace' (подставить знак замены). Для файлов, сохраненных в Блокноте с BOM, подходит кодировка 'utf-8-sig'.

В текстовом режиме Python при чтении превращает любые окончания строк (\r\n Windows и \n Linux) в \n, а при записи на Windows обратно в \r\n. Поведение меняет параметр newline. Например, модуль csv требует открывать файл с newline=''.

Бинарные файлы и позиция в файле

Картинки, архивы, PDF открывают в режимах rb и wb. Кодировку для них не указывают, а читаются и записываются объекты bytes. Так можно, например, скопировать файл блоками по 64 КБ:

with open('photo.jpg', 'rb') as src, open('copy.jpg', 'wb') as dst:
    while chunk := src.read(65536):
        dst.write(chunk)

Каждый открытый файл хранит текущую позицию. tell() возвращает ее, seek(offset, whence) перемещает: whence=0 считает от начала, 1 от текущего места, 2 от конца. В текстовом режиме смещения от текущего места и от конца допускаются только нулевые, поэтому произвольные переходы делают в бинарном режиме.

with open('photo.jpg', 'rb') as f:
    signature = f.read(4)
    f.seek(0, 2)            # в конец файла
    print(signature, f.tell(), 'байт')

Короткий путь через pathlib

Для небольших файлов есть методы объекта Path: они открывают, читают или пишут и закрывают файл одной строкой. Подробнее модуль описан в статье Pathlib вместо os.path.

from pathlib import Path

path = Path('hello.txt')
path.write_text('Привет!\n', encoding='utf-8')
print(path.read_text(encoding='utf-8'))
data = Path('photo.jpg').read_bytes()

Метод write_text() всегда перезаписывает файл. Для дозаписи или построчного чтения по-прежнему нужен open().

Методы файлового объекта

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

МетодНазначение
read(n=-1)Прочитать n символов или все до конца
readline()Прочитать одну строку
readlines()Прочитать все строки в список
write(s)Записать строку, вернуть число символов
writelines(lines)Записать набор строк без разделителей
seek(offset, whence=0)Переместить позицию
tell()Вернуть текущую позицию
flush()Сбросить буфер записи на диск
truncate(size=None)Обрезать файл до размера size
close()Закрыть файл

Частые вопросы

Короткие ответы на вопросы, которые возникают при первой работе с файлами.

Почему после записи файл пустой?

Данные сначала копятся в буфере и попадают на диск при закрытии файла или вызове flush(). Если файл открыт без with и не закрыт, часть текста может не записаться. Вторая частая причина: файл повторно открыли в режиме w, и он очистился.

Как прочитать файл в список без символов переноса?

Используйте f.read().splitlines() или генератор [line.rstrip('\n') for line in f]. Второй вариант не держит в памяти лишнюю копию всего текста.

Как записать в файл число или список?

write() принимает только строки, поэтому число преобразуют через str(), список склеивают методом '\n'.join(), а сложные структуры сохраняют через модуль json.

Чем режим a отличается от w?

Режим w обнуляет файл при открытии и пишет с начала. Режим a сохраняет содержимое и добавляет новые данные в конец, причем запись всегда идет в конец, даже после вызова seek().

Что делать при ошибке UnicodeDecodeError?

Файл сохранен не в той кодировке, которую ожидает Python. Укажите правильную явно, например encoding='cp1251' для старых файлов Windows, или errors='replace', если пропуск нескольких символов допустим.