8.1. Теория

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

8.1.1. Файлы и файловая система

Файл (англ. File) - именованная область данных на носителе информации.

Файлы хранятся в файловой системе - каталоге, определяющим способ организации, хранения и именования данных, а также задающем ограничения на формат и доступ к данным. На сегодняшний день наиболее популярными являются древовидные каталоги (также директории или папки) - файлы, содержащие записи о входящих в них файлах (Рисунок 8.1.1).

_images/08_01_01.png

Рисунок 8.1.1 - Пример древовидной организации файловой системы в ОС Windows [6].

Файловая система связывает носитель информации с одной стороны и программный интерфейс для доступа к файлам - с другой. Когда прикладная программа обращается к файлу, она не имеет никакого представления о том, каким образом расположена информация в конкретном файле, так же как и на каком физическом типе носителя (CD, жестком диске, магнитной ленте, блоке флеш-памяти или другом) он записан. Все, что знает программа - это имя файла, его размер и атрибуты (получая их от драйвера файловой системы). Именно файловая система устанавливает, где и как будет записан файл на физическом носителе (например, жестком диске) (Рисунок 8.1.2).

_images/08_01_02.png

Рисунок 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).

_images/08_01_03.png

Рисунок 8.1.3 - Файлы с последовательным и произвольным доступом [8]

Таблица 8.1.1 - Разница в доступе к файлам с последовательным и произвольным доступом
Характеристика Последовательный доступ Произвольный доступ
1 Метафора
_images/08_01_01_i.png
_images/08_01_02_i.png
2 Как хранят информацию? В неструктурированном виде (текстовом) В структурированном виде (двоичном)
2 Поиск Для поиска или обращения к определенному участку в файле необходимо его последовательно прочитать с начала Разрешен непосредственный переход к любой из записи
3 Можно править в текстовом редакторе? Да Нет, необходима специальная программа
4 Плюсы Компактность Скорость доступа
5 Основное применение Файлы конфигурации, документы Файлы баз данных и их производные
6 Пример Текстовый файл (*.txt и др.) База данных (*.mdb и др.)

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", особенно если есть вероятность работы программы на различных ОС.

Открытие файлов связано с потреблением/резервированием ресурсов, поэтому после выполнения необходимых операций его следует закрыть.

class file
close()

Закрывает файл. После этого работа с файлом невозможна (чтение, запись и др.).

Общий цикл работы с файлом может выглядеть следующим образом (Листинг 8.1.1).

Листинг 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

Кодировка, используемая для строковых преобразований в файле.

closed

Возвращает True, если файл закрыт.

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 приведен пример работы с двоичным файлом.

Листинг 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 приведен пример работы с текстовым файлом.

Листинг 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:

Содержимое файла 08_01_04_data.txt | скачать
Когда дети будут смотреть на великих учёных так же,
как они смотрят на знаменитых актёров и музыкантов,
человечество совершит большой прорыв.

Брайан Грин
https://ru.wikipedia.org/wiki/Грин,_Брайан_Рэндолф
Листинг 8.1.4 - Различные способы чтения текстового файла целиком | скачать
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.

Листинг 8.1.5 - Использование pickle для загрузки/сохранения объектов Python | скачать
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.

_images/08_01_04.png

Рисунок 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).

_images/08_01_05.png

Несмотря на наличие стандарта (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 (а-б).

Листинг 8.1.6 (а) - Работа с CSV-файлом в Python (последовательность) | скачать
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']
Листинг 8.1.6 (б) - Работа с CSV-файлом в Python (словарь) | скачать
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).

Листинг 8.1.7 - Пример JSON-файла | скачать
{
	"ФИО": "Иванов Сергей Михайлович",
	"ЕГЭ": {
		"Математика": 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.

Листинг 8.1.8 - Работа с JSON-форматом в Python | скачать
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/, которые могут как указать место ошибки, так и оформить его по стандарту.


[1]Sebesta, W.S Concepts of Programming languages. 10E; ISBN 978-0133943023.
[2]Python - официальный сайт. URL: https://www.python.org/.
[3]Python - FAQ. URL: https://docs.python.org/3/faq/programming.html.
[4]Саммерфилд М. Программирование на Python 3. Подробное руководство. — М.: Символ-Плюс, 2009. — 608 с.: ISBN: 978-5-93286-161-5.
[5]Лучано Рамальо. Python. К вершинам мастерства. — М.: ДМК Пресс , 2016. — 768 с.: ISBN: 978-5-97060-384-0, 978-1-491-94600-8.
[6]Что такое папка. URL: http://beginpc.ru/windows/chto-takoe-folder.
[7]The Volume Does Not Contain A Recognized File System – How To Fix. URL: https://www.powerdatarecovery.com/hard-drive-recovery/volume-not-contain-recognized-file-system.html.
[8]Последовательный доступ. URL: https://ru.wikipedia.org/wiki/Последовательный_доступ.