8.1. Теория¶
Файлы используются программами для долговременного хранения информации, как необходимой для собственной работы (например, настройки), так и полученной во время ее исполнения (результаты вычислений и т.д.). Подавляющее большинство программ сегодня в том или ином виде используют файлы, сохраняя результаты работы между сеансами запуска.
8.1.1. Файлы и файловая система¶
Файл (англ. File) - именованная область данных на носителе информации.
Файлы хранятся в файловой системе - каталоге, определяющим способ организации, хранения и именования данных, а также задающем ограничения на формат и доступ к данным. На сегодняшний день наиболее популярными являются древовидные каталоги (также директории или папки) - файлы, содержащие записи о входящих в них файлах (Рисунок 8.1.1).
Рисунок 8.1.1 - Пример древовидной организации файловой системы в ОС Windows [6].¶
Файловая система связывает носитель информации с одной стороны и программный интерфейс для доступа к файлам - с другой. Когда прикладная программа обращается к файлу, она не имеет никакого представления о том, каким образом расположена информация в конкретном файле, так же как и на каком физическом типе носителя (CD, жестком диске, магнитной ленте, блоке флеш-памяти или другом) он записан. Все, что знает программа - это имя файла, его размер и атрибуты (получая их от драйвера файловой системы). Именно файловая система устанавливает, где и как будет записан файл на физическом носителе (например, жестком диске) (Рисунок 8.1.2).
Рисунок 8.1.2 - Файловая система предоставляет интерфейс доступа к файлам для операционной системы [7]¶
8.1.1.1. Свойства файла¶
Файл может обладать различным набором свойств в зависимости от файловой системы.
В большинстве файловых систем файл имеет следующие свойства:
имя и расширение (как правило, называемые просто именем вместе): например,
моя_программа.py;дата/время (могут быть предусмотрены маркеры создания, модификации и последнего доступа);
владелец;
атрибуты (скрытый, системный и др.) и права доступа.
Имя файла имеет определенные ограничения в зависимости от файловой и операционной системы, в частности, допустимые знаки и длину наименования. Расширение указывается после имени через точку, имея назначение, в основном, для ОС Windows, где определяет приложение для запуска файла.
Примечание
В ОС Windows по умолчанию расширение файла скрыто от пользователя. Зачастую удобно «видеть» расширение, что можно включить в настройках: https://support.microsoft.com/ru-ru/kb/865219.
8.1.1.2. Путь к файлу: абсолютный и относительный¶
Для того, чтобы найти файл в файловой системе необходимо знать к нему путь - узлы дерева файловой системы, которые нужно пройти, чтобы до него добраться.
В операционных системах UNIX разделительным знаком при записи пути является /, в Windows — \: эти знаки служат для разделения названия каталогов, составляющих путь к файлу.
Путь может быть:
абсолютным (полным): указывает на одно и то же место в файловой системе вне зависимости от текущей рабочей директории или других обстоятельств;
относительным: путь по отношению к текущему рабочему каталогу пользователя или активных приложений.
Примеры путей для ОС Windows и UNIX:
ОС Windows:
абсолютный:
C:\user\python\example1.py;относительный:
example1.pyесли текущий каталогC:\user\python\;относительный:
python\example1.pyесли текущий каталогC:\user\;
ОС UNIX:
абсолютный:
/home/user/python/example1.py;относительный:
example1.pyесли текущий каталог/home/user/python/;относительный:
user/python/example1.pyесли текущий каталог/home/.
Примечание
См. более подробно про пути в разных операционных системах.
8.1.1.3. Операции с файлами¶
Все операции с файлами можно подразделить на 2 группы:
связанные с его открытием: открытие, закрытие файла, запись, чтение, перемещение по файлу и др.
выполняющиеся без его открытия: работа с файлом как элементом файловой системы - переименование, копирование, получение атрибутов и др.
При открытии файла, как правило, указываются:
имя файла;
права доступа
после чего операционная система возвращает специальный дескриптор файла (идентификатор), однозначно определяющий, с каким файлом далее будут выполняться операции. После открытия доступен файловый указатель - число, определяющее позицию относительно начала файла.
8.1.1.4. Виды файлов¶
По способу организации файлы делятся на файлы с последовательным и произвольным доступом (Рисунок 8.1.3, Таблица 8.1.1).
Рисунок 8.1.3 - Файлы с последовательным и произвольным доступом [8]¶
№ |
Характеристика |
Последовательный доступ |
Произвольный доступ |
|---|---|---|---|
1 |
Метафора |
|
|
2 |
Как хранят информацию? |
В неструктурированном виде (текстовом) |
В структурированном виде (двоичном) |
2 |
Поиск |
Для поиска или обращения к определенному участку в файле необходимо его последовательно прочитать с начала |
Разрешен непосредственный переход к любой из записи |
3 |
Можно править в текстовом редакторе? |
Да |
Нет, необходима специальная программа |
4 |
Плюсы |
Компактность |
Скорость доступа |
5 |
Основное применение |
Файлы конфигурации, документы |
Файлы баз данных и их производные |
6 |
Пример |
Текстовый файл ( |
База данных ( |
8.1.2. Файловый объект в Python¶
В Python работа с файлами осуществляется через специальный абстрактный файловый объект. В зависимости от способа создания такого объекта, он может быть привязан как к физическому файлу на диске, так и другому устройству, поддерживающему схожие операции (стандартный ввод/вывод и пр.).
Стандартный способ создания файлового объекта - функция open():
- open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)¶
Открывает файл и возвращает файловый объект. Если файл не может быть открыт, возбуждается исключение
OSErrorи его потомки (FileNotFoundErrorи др.).Некоторые из параметров:
- Параметры:
file – путь к файлу (например, строка) или файловый дескриптор;
mode –
режим открытия файла:
Символ
Описание
'r'Открыть для чтения (по умолчанию)
'w'Открыть для записи (если файл существует, то очищается)
'x'Открыть для создания с эксклюзивными правами (ошибка, если файл существует)
'a'Открыть для добавления (если файл существует)
'+'Открыть для чтения и записи
't'Текстовый режим (по умолчанию)
'b'Двоичный режим
Двоичный/текстовый режимы могут быть скомбинированы с другими: например, режим
'rb'позволит открыть на чтение бинарный файл;encoding – наименование кодировки, используемой при чтении/записи файла (например,
'utf-8'); параметр имеет смысл только для текстового режима.
Предупреждение
Кодировка файла
При открытии файла Python по умолчанию использует кодировку, предпочитаемую операционной системой. Для определения кодировки по умолчанию выполните код:
import locale
locale.getpreferredencoding(False) # 'cp1251' на российской сборке ОС Windows
Старайтесь указывать кодировку файла явно, например, encoding="utf-8", особенно если есть вероятность работы программы на различных ОС.
Открытие файлов связано с потреблением/резервированием ресурсов, поэтому после выполнения необходимых операций его следует закрыть.
Общий цикл работы с файлом может выглядеть следующим образом (Листинг 8.1.1).
# При работе с файлами всегда целесообразно использовать исключения
# 1. Стандартный способ открытия файла с обработкой исключений
fh = None
try:
fh = open("data.txt", encoding="utf-8")
#
# Чтение и запись файла
#
except Exception as e:
print("Ошибка при работе с файлом:", e)
finally:
if fh: # Если файл не открылся, значит 'fh' == None и закрывать его не нужно
fh.close()
# 2. Для упрощения кода по выделению и высвобождению ресурсов в Python
# предусмотрены специальные объекты - менеджеры контекста,
# которые могут самостоятельно следить за использованием ресурсов
#
# Наиболее часто менеджеры контекста вызываются с использованием ключевого слова with
try:
with open("data2.txt", encoding="utf-8") as fh:
#
# Чтение и запись файла
#
except Exception as e:
print("Ошибка при работе с файлом:", e)
Примечание
В большинстве примеров данной темы подробная обработка исключений опущена для того, чтобы сосредоточиться на демонстрации конкретных возможностей.
При самостоятельном написании программ не следует забывать добавлять обработку исключений - программа должна адекватно реагировать на возможные нестандартные ситуации (используемые файлы может изменить пользователь или другая программа).
8.1.3. Работа с файлами в Python¶
8.1.3.1. Основные свойства и методы¶
Файловый объект предоставляет ряд свойств и методов для работы с файлами. Большинство методов универсально и предполагают работу (чтение/запись) со строками в указанной кодировке (str для текстовых файлов) или с набором байт (bytes для двоичных файлов).
- class file¶
- name¶
Имя файла (если имеется).
- mode¶
Режим, в котором был открыт файл.
- encoding¶
Кодировка, используемая для строковых преобразований в файле.
- close()¶
Закрывает файл. После этого работа с файлом невозможна (чтение, запись и др.).
- read(count)¶
Читает до
countбайт из файлового объекта. Если значениеcountне определено, то читаются все байты, начиная от текущей позиции и до конца.Если ничего не было прочитано (конец файла), возвращается пустой объект
strилиbytes.
- readinto(ba)¶
Читает до
len(ba)байт в объектbaтипаbytearrayи возвращает число прочитанных байт (0, если был достигнут конец файла).Доступен только в двоичном режиме.
- readline(count)¶
Читает следующую строку (до
countбайт, если значениеcountопределено и число прочитанных байтов было достигнуто раньше, чем встретился символ перевода строки'\n'), включая символ перевода строки'\n'.
- readlines(sizehint)¶
Читает все строки до конца файла и возвращает их в виде списка.
Если значение аргумента
sizehintопределено, то будет прочитано примерноsizehintбайт (если файл поддерживает такую возможность).
- write(s)¶
Записывает в файл объект
sтипа:strдля текстового режима;bytes/bytearrayдля двоичного режима.
Примечание
Запись в файл возможна и с помощью стандартной функции
print(), установив ключевой параметрfileв открытый файловый объект.
- writelines(seg)¶
Записывает в файл последовательность объектов типа:
strдля текстового режима;bytes/bytearrayдля двоичного режима.
- flush()¶
При работе с файлами Python по умолчанию использует буфер определенного размера. Вызов методов записи приводит к записи в буфер, после чего в определенный момент производится очистка буфера и передача сигнала для записи данных на диск.
Метод
flush()вызывает принудительное очистку буфера. В большинстве случаев вызывать его напрямую не нужно.
- close()¶
Закрывает файл. После этого работа с файлом невозможна (чтение, запись и др.).
8.1.3.2. Простое чтение и запись¶
В Листинге 8.1.2 приведен пример работы с двоичным файлом.
human = dict(name="Михаил Толстых", age=35, weight=90.5)
filename = "08_01_02_data.txt"
# 1. Запись в файл
# При записи бинарных файлов все данные должны быть преобразованы в тип bytes
# Удобно выполнить преобразование через метод str.encode()
fh = None
try:
fh = open(filename, "wb")
fh.write(bytes(human["name"].encode("utf-8")))
fh.write(bytes(str(human["age"]).encode("utf-8")))
fh.write(bytes(str(human["weight"]).encode("utf-8")))
finally:
if fh:
fh.close()
# 2. Чтение из файла
# При чтении бинарных файлов необходимо точно знать, сколько байт
# прочитать и как их декодировать, используя bytes.decode()
# При редактировании файла в стороннем редакторе файл может быть не читаем
fh = None
try:
fh = open(filename, "rb")
name = fh.read(27).decode("utf-8")
age = int(fh.read(2).decode("utf-8"))
weight = float(fh.read(4).decode("utf-8"))
print(name, age, weight) # Михаил Толстых 35 90.5
finally:
if fh:
fh.close()
Примечание
Работа с бинарными файлами не рассматривается детально в настоящем курсе и, в целом, аналогична работе с текстовыми файлами с необходимостью работы не со строкой, а набором байт с необходимой перекодировкой.
Больше примеров: http://www.devdungeon.com/content/working-binary-data-python.
В Листинге 8.1.3 приведен пример работы с текстовым файлом.
human = dict(name="Михаил Толстых", age=35, weight=90.5)
filename = "08_01_03_data.txt"
# 1. Запись в файл
# При записи текстовых файлов все данные должны быть преобразованы в тип str
# По умолчанию, write() не добавляет перенос строки, однако его можно добавить самостоятельно
fh = None
try:
fh = open(filename, "w", encoding="utf-8")
# При добавлении переноса записываемые данные будут на отдельной строке
fh.write(human["name"] + "\n")
fh.write(str(human["age"]) + "\n")
# Как альтернатива - print() позволяет не переводить в строку и не добавлять перенос вручную
print(human["weight"], file=fh)
finally:
if fh:
fh.close()
# 2. Чтение из файла
# Для чтения отдельной строки достаточно вызвать метод readline().
# В конце полученной строки знак переноса - \n,
# который можно убрать, например, методом str.strip()
fh = None
try:
fh = open(filename, encoding="utf-8")
# Читаем первые 3 строки и преобразуем при необходимости
name = fh.readline().strip()
age = int(fh.readline())
weight = float(fh.readline())
print(name, age, weight) # Михаил Толстых 35 90.5
finally:
if fh:
fh.close()
8.1.3.3. Чтение файла целиком¶
Чтение файла, приведенное в Листинге 8.1.3 не подразумевает, что содержимое файла может меняться.
Учитывать такие изменения можно, прочитав файл целиком:
в одну строку;
в список строк;
построчно, пока не достигнут конец файла.
Примеры реализации данных вариантов приведены в Листинге 8.1.4 на примере файла 08_01_04_data.txt:
Когда дети будут смотреть на великих учёных так же,
как они смотрят на знаменитых актёров и музыкантов,
человечество совершит большой прорыв.
Брайан Грин
https://ru.wikipedia.org/wiki/Грин,_Брайан_Рэндолф
filename = "08_01_04_data.txt"
# В данном примере обработка исключений не приводится, чтобы
# сосредоточить внимание на чтении файлов
# 1. Чтение из файла (в одну строку)
with open(filename, encoding="utf-8") as fh:
data = fh.read()
print(data)
# 2. Чтение из файла (в список)
with open(filename, encoding="utf-8") as fh:
data = fh.readlines()
print(data)
# ['Когда дети будут смотреть на великих учёных так же,\n',
# 'как они смотрят на знаменитых актёров и музыкантов,\n',
# 'человечество совершит большой прорыв.\n',
# '\n',
# 'Брайан Грин\n',
# 'https://ru.wikipedia.org/wiki/Грин,_Брайан_Рэндолф\n']
# 3. Чтение из файла (построчно)
with open(filename, encoding="utf-8") as fh:
for line in fh:
print(line.strip())
8.1.4. Сериализация и десериализация¶
Чтение/запись простых типов (например, чисел или строк) не представляет большого труда, однако с увеличением объема информации появляется необходимость эффективно сохранять/загружать более сложные структуры данных (например, словари). Кроме того, модульная архитектура современного программного обеспечения приводит к необходимости обмена данными между различными модулями, а также между приложениями в целом, для чего необходимо иметь возможность удобно обмениваться данными.
Сериализация — процесс перевода какой-либо структуры данных в последовательность битов. Десериализация — обратный процесс.
Чаще всего сериализация используется для сохранения объектов в файлы или передачи их по сети.
8.1.4.1. Модуль pickle¶
Одним из способов, позволяющих сериализовать/десериализовать данные в Python, является использование стандартного модуля pickle, при помощи которого можно сохранять любой объект Python в двоичном файле, а затем извлекать его обратно.
Основные функции модуля:
- pickle.dump(obj, file, protocol=None, *, fix_imports=True)¶
Сериализует объект
objи записывает его в файлfile.Некоторые из параметров:
- Параметры:
obj – объект для записи;
file – файловый объект;
protocol – версия формата
pickle.
- pickle.load(file, *, fix_imports=True, encoding='ASCII', errors='strict')¶
Читает и десериализует содержимое файла
file, возвращая созданный объект (структуру).Некоторые из параметров:
- Параметры:
file – файловый объект.
Пример работы с модулем pickle приведен в Листинге 8.1.5.
import pickle
filename = "08_01_05_data.txt"
# список покупок
shoplist = {"фрукты": ["яблоки", "манго"],
"овощи": ["морковь"],
"бюджет": 1000}
# Запись в файл
with open(filename, "wb") as fh:
pickle.dump(shoplist, fh) # помещаем объект в файл
# Считываем из хранилища
shoplist_2 = []
with open(filename, "rb") as fh:
shoplist_2 = pickle.load(fh) # загружаем объект из файла
print(shoplist_2) # {'бюджет': 1000, 'овощи': ['морковь'], 'фрукты': ['яблоки', 'манго']}
Формат файла, создаваемого pickle, приведен на Рисунке 8.1.4.
Рисунок 8.1.4 - Содержимое файла с данными при использовании pickle (в редакторе Notepad++)¶
Минусы формата pickle:
специфичен для Python (не может быть использован, если файл будет читаться с использованием других языков программирования);
небезопасен (десериализация готовых конструкций языка может привести к выполнению ненадежного кода).
8.1.4.2. Популярные форматы файлов¶
Большое количество данных в совокупности с их разнородностью привело к появлению специальных форматов файлов, позволяющих хранить различные объемы связанной информации и не привязанных к конкретному языку программирования.
Среди них одними из наиболее популярных являются:
CSV (англ. Comma-Separated Values - значения, разделенные запятыми);
JSON (англ. JavaScript Object Notation) - текстовый формат обмена данными, основанный на JavaScript;
XML (англ. eXtensible Markup Language - расширяемый язык разметки);
YAML (англ. YAML Ain’t Markup Language - «YAML - Не язык разметки»);
INI (англ. Initialization file - файл инициализации);
и др.
Подавляющее большинство форматов поддерживается Python (стандартными или сторонними модулями и пакетами).
8.1.4.2.1. CSV¶
CSV (англ. Comma-Separated Values - значения, разделенные запятыми, 2005 г.) - текстовый формат, предназначенный для представления табличных данных. Каждая строка файла - это одна строка таблицы, где значения отдельных колонок разделяются разделительным символом (англ. delimiter) запятой , и заключаются в кавычки " (Рисунок 8.1.5).
Несмотря на наличие стандарта (RFC 4180), на сегодняшний день под CSV, как правило, понимают набор значений, разделенных произвольными разделителями, в произвольной кодировке с произвольными окончаниями строк. Это значительно затрудняет перенос данных из одних программ в другие, несмотря на всю простоту реализации поддержки CSV (так, например, Microsoft Excel не всегда открывает стандартные разделенные запятыми данные).
В Python работа с CSV-файлами поддерживается стандартным модулем csv, предоставляющем следующие основные объекты и функции:
- csv.reader(csvfile, dialect='excel', **fmtparams)¶
Создает и возвращает объект для чтения последовательности из CSV-файла.
Некоторые из параметров:
- Параметры:
csvfile – итерируемый объект, возвращающий строку на каждой итерации (например, файловый объект в текстовом режиме доступа);
dialect – диалект CSV (набор специальных параметров);
fmtparams – дополнительные настройки (совокупность кавычек, разделителей и т.д.).
- csv.writer(csvfile, dialect='excel', **fmtparams)¶
Создает и возвращает объект для записи последовательности в CSV-файл.
Некоторые из параметров:
- Параметры:
csvfile – любой объект, поддерживающий метод записи
write();dialect – аналогично
csv.reader();fmtparams – аналогично
csv.reader().
- class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)¶
Создает и возвращает объект для чтения данных из CSV-файла как словаря значений.
Некоторые из параметров:
- Параметры:
csvfile – итерируемый объект, возвращающий строку на каждой итерации (например, файловый объект в текстовом режиме доступа);
fieldnames – список наименований столбцов (если не задан, используется первая строка файла).
- class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)¶
Создает и возвращает объект для записи данных как словаря значений в CSV-файл.
Некоторые из параметров:
- Параметры:
csvfile – любой объект, поддерживающий метод записи
write();fieldnames – список наименований столбцов.
- class csv.Writer¶
- writerow(row)¶
Записывает последовательность
rowв CSV-файл.
- writerows(rows)¶
Записывает список последовательностей
rowsв CSV-файл.
- class csv.DictWriter¶
- writeheader()¶
Записывает в файл заголовки файла, переданные при создании класса.
- writerow(row)¶
Записывает словарь
rowв CSV-файл.
- writerows(rows)¶
Записывает список словарей
rowsв CSV-файл.
- exception csv.Error¶
Класс исключения, возбуждаемый при ошибке в работе любой из функций модуля.
Пример использования модуля csv приведен в Листинге 8.1.6 (а-б).
import csv
filename = "08_01_06_a_data.csv"
# список покупок
shoplist = {"яблоки": [2, 100], "манго": [3, 250], "морковь": [1, 35]}
# Запись в файл
with open(filename, "w", encoding="utf-8", newline="") as fh:
writer = csv.writer(fh, quoting=csv.QUOTE_ALL)
writer.writerow(["Наименование", "Вес", "Цена/кг."]) # Заголовки столбца
for name, values in sorted(shoplist.items()):
writer.writerow([name, *values])
writer.writerow(["рис", "4", "70"]) # Допишем произвольную запись
# Содержимое файла
#
# "Наименование","Вес","Цена/кг."
# "манго","3","250"
# "морковь","1","35"
# "яблоки","2","100"
# "рис","4","70"
# Чтение файла
rows = []
with open(filename, "r", encoding="utf-8") as fh:
reader = csv.reader(fh)
rows = list(reader) # reader - итерируемый объект и может быть преобразован в список строк
for row in rows:
print(row)
# Вывод на экран
#
# ['Наименование', 'Вес', 'Цена/кг.']
# ['манго', '3', '250']
# ['морковь', '1', '35']
# ['яблоки', '2', '100']
# ['рис', '4', '70']
import csv
filename = "08_01_06_b_data.csv"
# список покупок
shoplist = {"яблоки": [2, 100], "манго": [3, 250], "морковь": [1, 35]}
# Запись в файл
with open(filename, "w", encoding="utf-8", newline="") as fh:
writer = csv.DictWriter(fh, fieldnames=["name", "weight", "price"], quoting=csv.QUOTE_ALL)
writer.writeheader() # Записывает заголовки в файл
for name, values in sorted(shoplist.items()):
writer.writerow(dict(name=name, weight=values[0], price=values[1]))
# Содержимое файла
#
# "name","weight","price"
# "манго","3","250"
# "морковь","1","35"
# "яблоки","2","100"
# Чтение файла
rows = []
with open(filename, "r", encoding="utf-8") as fh:
reader = csv.DictReader(fh)
rows = list(reader) # reader - итерируемый объект и может быть преобразован в список строк
for row in rows:
print(row)
# Вывод на экран
#
# {'name': 'манго', 'weight': '3', 'price': '250'}
# {'name': 'морковь', 'weight': '1', 'price': '35'}
# {'name': 'яблоки', 'weight': '2', 'price': '100'}
8.1.4.2.2. JSON¶
JSON (англ. JavaScript Object Notation, 1999 г.) - текстовый формат обмена данными, основанный на JavaScript. Одно из преимуществ - JSON легко читается людьми (англ. human-readable) (Листинг 8.1.7).
{
"ФИО": "Иванов Сергей Михайлович",
"ЕГЭ": {
"Математика": 90,
"Физика": 70,
"Информатика": 80
},
"Хобби": ["Рисование", "Плавание"],
"Возраст": 25.5,
"ДомЖивотные": null
}
JSON-текст представляет собой одну из двух структур:
набор пар
ключ: значение(словарь в терминологии Python), где ключ - строка, значение - любой тип;упорядоченный набор значений (список в терминологии Python).
Значением может являться:
строка (в кавычках);
число;
логическое значение (
true/false);null;одна из структур.
Одним из преимуществ JSON является близкое соответствие Python по типам данных. Работа с JSON-форматом поддерживается стандартным пакетом json, предоставляющем следующие основные функции:
- json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)¶
Сериализует объект
obj, возвращая строку в JSON-формате.Некоторые из параметров:
- Параметры:
obj – сериализуемый объект;
ensure_ascii – если равен
False, запись не-ASCII значений происходит в файл «как есть», без преобразования в Unicode;indent – величина отступа для вложенных структур.
- json.loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)¶
Десериализует объект (в том числе файловый)
s, возвращая структуру в Python.При ошибке десериализации возбуждается исключение JSONDecodeError.
- exception json.JSONDecodeError(msg, doc, pos, end=None)¶
Класс исключения, возбуждаемый при ошибке в работе некоторых функций пакета.
Пример работы с JSON-форматом приведен в Листинге 8.1.8.
import json
filename = "08_01_08_data.json"
info = {
"ФИО": "Иванов Сергей Михайлович",
"ЕГЭ": {
"Математика": 90,
"Физика": 70,
"Информатика": 80
},
"Хобби": ["Рисование", "Плавание"],
"Возраст": 25.5,
"ДомЖивотные": None
}
# Запись структуры в файл в JSON-формате
with open(filename, "w", encoding="utf-8") as fh:
fh.write(json.dumps(info, ensure_ascii=False, indent=4))
# Пример содержимого файла:
# {
# "Хобби": [
# "Рисование",
# "Плавание"
# ],
# "ЕГЭ": {
# "Информатика": 80,
# "Математика": 90,
# "Физика": 70
# },
# "ФИО": "Иванов Сергей Михайлович",
# "ДомЖивотные": null,
# "Возраст": 25.5
# }
# Чтение из файла JSON-формата
info_2 = []
with open(filename, encoding="utf-8") as fh:
info_2 = json.loads(fh.read())
print(info_2)
# {'ФИО': 'Иванов Сергей Михайлович', 'ЕГЭ': {'Информатика': 80, 'Математика': 90, 'Физика': 70},
# 'Хобби': ['Рисование', 'Плавание'], 'Возраст': 25.5, 'ДомЖивотные': None}
Примечание
Валидация и оформление JSON-файлов
При возникновении ошибки чтения файла JSON-формата рекомендуется проверить его синтаксис с использованием специальных онлайн-сервисов, например, https://jsonformatter.curiousconcept.com/, которые могут как указать место ошибки, так и оформить его по стандарту.