2.27. Чтение и запись

Файлы хранятся на диске; Python обращается к ним через open(), которая возвращает файловый объект, чьи методы читают и записывают лежащие в основе байты.

2.27.1. open и режимы

Первый аргумент – это путь; второй – режим – короткая строка, сообщающая Python, как будет использоваться файл:

  • "r" – чтение (по умолчанию). Открывает существующий файл для чтения.

  • "w" – запись. Создаёт новый файл или усекает существующий до пустого.

  • "a" – добавление. Открывает файл для записи в его конец без усечения.

  • "b", добавленное к любому из вышеперечисленных ("rb", "wb", "ab") – двоичный режим. Содержимое файла – это bytes, а не str.

f = open("notes.txt", "r")
text = f.read()
f.close()

2.27.2. Используйте менеджер контекста

Приведённый выше шаблон оставляет утечку файлового дескриптора, если что-либо между open() и close возбуждает исключение. Решение – инструкция with (см. менеджеры контекста):

with open("notes.txt") as f:
    text = f.read()

# f is closed here, even if read() failed

Это стандартная форма – пишите так каждый раз.

2.27.3. Чтение

Файловые объекты поддерживают несколько стилей чтения:

  • io.IOBase.read() – прочитать весь файл (или N байт) и вернуть его в виде одной строки (или объекта bytes).

  • io.IOBase.readline() – прочитать одну строку, включая завершающий "\n".

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

with open("log.txt") as f:
    for line in f:
        print(line.rstrip())

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

2.27.4. Запись

Откройте файл в режиме "w" и используйте io.IOBase.write():

with open("out.txt", "w") as f:
    f.write("hello\n")
    f.write("world\n")

io.IOBase.write() не добавляет символ новой строки – он записывает ровно те байты (или символы в текстовом режиме), которые вы ему передаёте.

2.27.5. Текстовый режим против двоичного

Текстовый режим (по умолчанию, "r" / "w" без "b") декодирует входящие байты в str с использованием кодировки по умолчанию и кодирует исходящие str обратно в байты. Используйте его для конфигурации, журналов, JSON – всего, что является текстом.

Двоичный режим ("rb" / "wb") пропускает шаг декодирования и возвращает bytes. Используйте его для изображений, записей, упакованных через struct, сетевых захватов – всего, где важен каждый байт и файл не предназначен для чтения человеком.

2.27.6. Перечисление и удаление файлов

Модуль os предоставляет операции с файловой системой, которых нет у самого файлового объекта:

  • os.listdir() – возвращает список имён в каталоге.

  • os.remove() – удалить файл.

  • os.rename() – переименовать файл.

  • os.stat() – метаданные файла (размер, время изменения, …).

  • os.mkdir() – создать новый каталог.

import os

for name in os.listdir("/"):
    print(name)

Перехватывайте OSError вокруг этих операций, когда файла или каталога может не быть – эта операция – одно из распространённых мест, где в реальных скриптах появляются исключения.