logo
Ещё

Работа с файлами в Python

Все переменные, которые вы создаете, исчезнут после закрытия программы – так работает временная память устройства. Если вы хотите сохранить какую-то информацию на неопределенный срок – вам нужно записать ее в постоянное хранилище, на жесткий диск. Контейнеры для хранения информации на жестком диске – файлы, и Python предоставляет ряд встроенных методов для работы с ними.

3 важных принципа работы с файлами

Файл – это внешний ресурс, и ваше приложение – не единственное, которое хочет пользоваться внешними ресурсами. Когда дело касается памяти – операционная система может выдать каждому приложению свою «лужайку», на которой приложение делает все, что хочет; с файлами – сложнее, часто случается так, что одно приложение читает информацию, которую в файл помещает другое приложение. И это уже представляет проблему: если одно приложение пишет, а другое в это же время читает, то как читающий может быть уверен, что он читает свежую информацию. Все становится еще хуже, если 2 приложения одновременно пишут данные в файл: на выходе получится мешанина из двух разных потоков данных.

Чтобы решить все эти проблемы, операционная система устанавливает правило: одним конкретным файлом в конкретный момент времени может пользоваться только одно приложение. Если ваш «Hello world!» открыл файл для записи или чтения – ни одно другое приложение не может открыть этот же файл, пока вы его не закроете. Поэтому запомните:

  1. Файлы нужно открывать только тогда, когда они действительно вам нужны.
  2. Как только вы закончили работать с файлом – вам нужно его закрыть, чтобы другие приложения могли получить к нему доступ.
  3. Если вы работаете с уже существующим файлом – вы никогда не можете быть уверены, что им не пользуется кто-то еще (эту потенциальную ошибку всегда нужно обрабатывать).

Если вы будете держать эти принципы в голове, работать с файлами в Python (как и в любом другом ЯП) вам будет куда проще.

Открываем и закрываем файлы в Python

Итак, сначала научимся самому главному – открывать и закрывать файлы в Python. Открыть файл можно с помощью встроенной функции open(), сигнатура:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

Обязательный параметр – только первый, file, путь к файлу. Функция возвращает файловый объект, с которым можно работать через методы. По опциональным параметрам – mode рассмотрим отдельно, вкратце об остальных:

  • buffering: разрешить/запретить буферизацию и указать размер буфера при необходимости.
  • encoding: кодировка.
  • errors: тип политики обработки ошибок.
  • newline: какой символ считать символом конца строки.
  • closefd: оставлять ли файловый дескриптор открытым после закрытия самого файла.
  • opener: колбэк для кастомной функции открытия файла.

Если вам вдруг нужно узнать больше о каком-то из этих параметров – смотрите официальную документацию.

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

Режим

Описание

С каким файлом работаем?

t

Текстовый файл. Является режимом по умолчанию – если работаем с текстом, то “t” писать не надо, мы рассказываем про него только для того, чтобы вы знали о его существовании

b

Бинарный файл. По суть – набор байт. Может быть текстом, картинкой, набором структур и вообще чем угодно. “b” нужно указывать, если “b” нет – Python считает, что мы работаем с текстовым файлом.

Хотим создать, прочитать ИЛИ записать

r

Читать данные из файла. Если файла не существует – получаем исключение

w

Записать данные в файл. Если файла не существует – он будет создан. Если файл уже существует и хранит в себе какую-то информацию – она будет удалена(!)

x

Создать файл. Если файл с таким именем уже существует – получаем исключение

a

Записать данные в конец файла. Если он уже существует – данные будут записаны после тех, что уже хранятся в файле. Если он не существует – он будет создан

Хотим прочитать И записать

r+

Открывает файл для чтения и записи, если файла с таким именем нет – генерирует исключение

w+

Открывает файл для чтения и записи, если файл уже существует – перезаписывает его

a+

Открывает файл для чтения и записи, если файл уже существует – записывает данные в конец файла

Итак, для работы с файлом вам нужно открыть его, выбрав нужный режим (или открыв в стандартном режиме – tr). После того, как вы с ним поработаете, файл нужно будет закрыть через .close(). Синтаксис будет выглядеть так:

file = open("example.txt", "w")

file.write("Hello, world!")

file.close()

Но тут есть проблема – file.write() может генерировать исключения, и если это случится – file.close() не будет исполнен. Для того, чтобы избежать этого, нужно использовать диспетчер контекста with – он автоматически закроет файл, когда поток исполнения выйдет из блока:

with open("example.txt", "w") as file:

file.write("Hello, world!")

Такое открытие файла считается хорошей практикой.

Читаем данные и записываем их

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

with open("example.txt", "r", encoding="utf-8") as file:

data = file.read()

print(data)

Прочитать следующую строчку можно с помощью метода .readline(), а если вы хотите прочитать сразу все строки – метод .readlines() вернет вам список строк:

with open("example.txt", "r", encoding="utf-8") as file:

lines = file.readlines()

for line in lines:

print(line.strip())

В целом предпочтительно читать файлы по строкам, потому что если вы случайно прикажете интерпретатору считать файл весом 2 Гб в переменную – он это сделает.

С записью все так же, только вместо .read() мы используем .write() (или .writelines(), которому передаем список строк):

with open("example.txt", "w", encoding="utf-8") as file:

file.write("Hello, world!\n")

file.write("Привет, мир!\n")

Не забывайте добавлять символ перевода строки в конце каждой – .write() этого не делает.

Еще один способ записи в файл – стандартный метод print(), которому в качестве аргумента передают имя файла:

with open("example.txt", "a", encoding="utf-8") as file:

print("Hello, sravni.ru", file=file)

Все эти методы чтения и записи позволяют читать/записывать данные символ за символом, строка за строкой. За последовательность отвечает курсор – после чтения/записи каждого нового символа он смещается. Вы можете управлять курсором с помощью функции .seek():

with open("example.txt", "w+", encoding="utf-8") as file:

file.write("Hello, world!\n")

file.write("Привет, мир!\n")

file.seek(0)

content = file.read()

print(content)

file.seek(7)

content = file.read()

print(content)

Здесь мы записали данные, вернулись в начало файла, считали весь файл и вывели его, переместились на 7-й байт, считали все от 7 байта до конца файла и снова вывели содержимое. Главное – помните, что .seek() считает байты, а не символы – это может оказаться проблемой, если кодировка текста выделяет больше 1 байта на символ.

Работа с файловой системой

Python предоставляет несколько библиотек для работы с файловой системой, базовые манипуляции можно найти в разделе «Files and directories» модуля os, для сложных операций с файлами есть модуль shutil. Разбор этой сложной темы выходит за рамки данного материала, поэтому просто вкратце перечислим интересные методы – больше информации о них вы найдете в документации:

  • os.getcwd() – узнать текущую директорию.
  • mkdir() – создать директорию.
  • os.makedirs() – создать вложенные директории.
  • remove() – удалить файл.
  • rmdir() – удалить директорию.
  • Path.glob() – получить список всех файлов в определенном месте.
  • file.rename() – переименовать или переместить файл.
  • copy() – скопировать файл.
  • os.path.exists() – проверить, существует ли путь.
  • Path.name и Path.suffix – узнать имя и расширение файла.
  • Пакет zipfile – архивирование и разархивирование.

Вывод

Тезисно:

  • Файлы нужны для того, чтобы сохранять данные, которые будут потеряны при выключении устройства.
  • Если вы открываете файл – вам потом нужно его закрыть, чтобы освободить ресурс (файл) для других приложений.
  • Файлы открываются с помощью open(), закрываются с помощью close(). Можно использовать менеджер контекста with – тогда файлы будут закрываться автоматически.
  • Чтение данных – через .read() объекта файла, запись – через .write() объекта файла.
  • С помощью Python можно работать с файловой системой – создавать каталоги, перемещать файлы и так далее.