Запись данных в файл в текстовом и бинарном режимах

Курс по Python: https://stepik.org/course/100707

На этом занятии вы узнаете, как можно сохранять данные в файл. Первое, что нам нужно сделать – это открыть файл на запись. Для этого вторым аргументом функции open() следует указать строку "w":

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

(Если не указывать ничего, как это мы делали на прошлых уроках, то файл будет открыт на чтение, или же, можно явно прописать "r" – значение по умолчанию).

Итак, мы открыли файл на запись и далее, чтобы поместить в него какую-либо текстовую информацию следует вызвать метод write, следующим образом:

file.write("Hello World!")
file.close()

В результате будет создан файл out.txt (если его ранее не было) со строкой «Hello World!». Причем, этот файл будет располагаться в том же каталоге, что и исполняемый файл. Также после записи всей нужной информации в файл, его следует обязательно закрывать! Иначе, часть информации может не сохраниться. Как я уже говорил, метод close() нужно вызывать всегда после завершения работы с файлом.

Отлично, это у нас получилось! Давайте теперь запишем метод write со строкой «Hello»:

file.write("Hello")

и снова выполним эту программу. Смотрите, в нашем файле out.txt прежнее содержимое исчезло и появилось новое – строка «Hello». То есть, когда мы открываем файл на запись, то прежнее содержимое удаляется. Вот этот очень важный момент всегда следует иметь в виду – открывая файл на запись, его прежнее содержимое автоматически удаляется!

Те из вас, кто смотрел предыдущее занятие, сейчас могут заметить, что при открытии файла на запись могут возникать различные файловые ошибки, поэтому критический блок (кода открытия файла и записи информации) лучше поместить в блок try, а все операции с файлом выполнять через менеджер контекста:

try:
    with open("out.txt", "w") as file:
        file.write("Hello World!")
except:
    print("Ошибка при работе с файлом")

Об этом всегда следует помнить, при работе с файлами! Чтобы программа работала надежно даже в нештатных ситуациях, необходима конструкция try / except и менеджер контекста with.

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

        file.write("Hello1")
        file.write("Hello2")
        file.write("Hello3")

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

Если мы хотим, чтобы эти строки шли друг под другом, то в конце каждой из них достаточно указать символ переноса строки:

        file.write("Hello1\n")
        file.write("Hello2\n")
        file.write("Hello3\n")

Однако, если нам все же нужно, мы можем выполнять дозапись информации в файл. Для этого его следует открыть в режиме ‘a’ (сокращение от англ. слова append – добавление):

with open("out.txt", "a") as file:
    ...

Выполняя эту программу, мы видим в файле уже шесть строчек.

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

file.read()

то возникнет ошибка. Чтобы ее увидеть я поставлю комментарии у блока try и снова запущу программу. Видим исключение UnsupportedOperation.

Если же мы хотим и записывать и считывать информацию, то можно воспользоваться режимом a+:

file = open("out.txt", "a+")

Так как здесь файловый указатель стоит на последней позиции, то для считывания информации, поставим его в самое начало:

        file.seek(0)
        print( file.read() )

А вот запись данных всегда осуществляется в конец файла, так как для записи используется другая файловая позиция и она указывает на конец файла.

Далее, если нам нужно записать несколько строк, представленных в какой-либо коллекции, то удобно воспользоваться методом writelines():

file.writelines(["Hello1\n", "Hello2\n"])

Это часто используется, если в процессе обработки текста у нас получается список из строк и его требуется целиком поместить в файл. Здесь метод writelines() незаменим.

Чтение и запись в бинарном режиме доступа

До сих пор мы с вами говорили о чтении и записи информации в текстовом режиме доступа. Есть еще другой – бинарный режим работы с файлами. Что такое бинарный режим доступа? Это когда данные из файла считываются один в один без какой-либо обработки. Обычно он используется для сохранения и считывания объектов целиком. Давайте предположим, что нам нужно сохранить в файл вот такой список:

books = [
    ("Евгений Онегин", "Пушкин А.С.", 200),
    ("Муму", "Тургенев И.С.", 250),
    ("Мастер и Маргарита", "Булгаков М.А.", 500),
    ("Мертвые души", "Гоголь Н.В.", 190)
]

Для этого откроем файл на запись в бинарном режиме:

file = open("out.bin", "wb")

Затем, для работы с бинарными данными подключим специальный встроенный модуль pickle:

import pickle

И вызовем его метод dump:

pickle.dump(books, file)

Все, мы сохранили этот объект в файл. Теперь прочитаем эти данные. Откроем файл на чтение в бинарном режиме:

file = open("out.bin", "rb")

и вызовем метод load модуля pickle:

bs = pickle.load(file)

Все, теперь переменная bs ссылается на эквивалентный список:

print( bs )

Аналогичным образом можно записывать и считывать сразу несколько объектов. Например, так:

import pickle
 
book1 = ["Евгений Онегин", "Пушкин А.С.", 200]
book2 = ["Муму", "Тургенев И.С.", 250]
book3 = ["Мастер и Маргарита", "Булгаков М.А.", 500]
book4 = ["Мертвые души", "Гоголь Н.В.", 190]
 
try:
    with open("out.bin", "wb") as file:
        pickle.dump(book1, file)
        pickle.dump(book2, file)
        pickle.dump(book3, file)
        pickle.dump(book4, file)
except:
    print("Ошибка при работе с файлом")

А, затем, считывание в том же порядке:

import pickle
 
try:
    with open("out.bin", "rb") as file:
        b1 = pickle.load(file)
        b2 = pickle.load(file)
        b3 = pickle.load(file)
        b4 = pickle.load(file)
except:
    print("Ошибка при работе с файлом")
 
print( b1, b2, b3, b4, sep="\n" )

Вот так в Python выполняется запись и считывание данных в бинарном режиме.

Надеюсь, из этого занятия вам стало понятно, как производится запись данных в файл, как делать дозапись информации, что такое бинарный и текстовый режимы доступа и как записывать и считывать информацию в бинарном режиме с помощью методов модуля pickle. До встречи на следующем занятии!

Курс по Python: https://stepik.org/course/100707

Видео по теме