Python читает JSON-файл
Обновлено: 21.11.2024
Если вам нужно обработать большой файл JSON в Python, очень легко не хватить памяти. Даже если необработанные данные умещаются в памяти, представление Python может еще больше увеличить использование памяти.
И это означает либо медленную обработку, когда ваша программа переключается на диск, либо сбой, когда у вас заканчивается память.
Одним из распространенных решений является потоковый синтаксический анализ, также известный как ленивый синтаксический анализ, итеративный синтаксический анализ или обработка фрагментами. Давайте посмотрим, как вы можете применить эту технику к обработке JSON.
Проблема: загрузка JSON с неэффективным использованием памяти в Python
В иллюстративных целях мы будем использовать этот файл JSON, достаточно большой (24 МБ), чтобы при загрузке заметно влиять на объем памяти. Он кодирует список объектов JSON (то есть словарей), которые выглядят как события GitHub, когда пользователи делают что-то с репозиториями:
Наша цель — выяснить, с какими репозиториями взаимодействовал конкретный пользователь. Вот простая программа на Python, которая делает это:
Результатом является словарь, сопоставляющий имена пользователей с наборами имен репозиториев.
Когда мы запустим это с помощью профилировщика памяти Fil, мы получим следующее:
Глядя на пиковое использование памяти, мы видим два основных источника выделения:
- Чтение файла.
- Декодирование полученных байтов в строки Unicode.
И если мы посмотрим на реализацию модуля json в Python, мы увидим, что json.load() просто загружает весь файл в память перед синтаксическим анализом!
Даже если загрузка файла является узким местом, это все равно вызывает некоторые вопросы. Исходный файл, который мы загрузили, имеет размер 24 МБ. Как только мы загружаем его в память и декодируем в текстовую (Unicode) строку Python, это занимает гораздо больше, чем 24 МБ. Почему так?
Небольшое отступление: строковое представление памяти в Python
Структурное представление Python оптимизировано для использования меньшего объема памяти в зависимости от содержимого строки. Во-первых, каждая строка имеет фиксированные накладные расходы. Затем, если строка может быть представлена в виде ASCII, для каждого символа используется только один байт памяти. Если в строке используется больше расширенных символов, она может в конечном итоге использовать до 4 байтов на символ. Мы можем увидеть, сколько памяти требуется объекту, используя sys.getsizeof() :
Обратите внимание, что все 3 строки имеют длину 1000 символов, но они используют разный объем памяти в зависимости от того, какие символы они содержат.
Если вы посмотрите на наш большой файл JSON, он содержит символы, которые не помещаются в ASCII. Поскольку она загружается как одна гигантская строка, эта целая гигантская строка использует менее эффективное представление памяти.
Решение для потоковой передачи
Понятно, что загрузка всего файла JSON в память — пустая трата памяти. Файл большего размера будет вообще невозможно загрузить.
Если файл JSON структурирован как список объектов, теоретически мы могли бы анализировать его по частям, а не все сразу. Полученный API, вероятно, позволит обрабатывать объекты по одному. И если мы посмотрим на алгоритм, который мы хотим запустить, это просто отлично; алгоритм не требует одновременной загрузки всех данных в память. Мы можем обрабатывать записи по одной.
Каким бы термином вы не назвали этот подход — потоковая передача, итеративный синтаксический анализ, фрагментация или чтение по требованию — это означает, что мы можем сократить использование памяти до:
- Текущие данные, которые обычно должны быть исправлены.
- Структура данных результата, которая в нашем случае не должна быть слишком большой.
Существует ряд библиотек Python, которые поддерживают этот стиль разбора JSON. в следующем примере я использовал библиотеку ijson.
В предыдущей версии при использовании стандартной библиотеки после загрузки данных файл больше не оставался открытым. С помощью этого API файл должен оставаться открытым, потому что синтаксический анализатор JSON считывает файл по запросу, когда мы перебираем записи.
API items() принимает строку запроса, в которой указывается, какую часть записи следует вернуть. В этом случае «элемент» просто означает «каждый элемент в списке верхнего уровня, который мы повторяем»; дополнительные сведения см. в документации по ijson.
Вот как выглядит использование памяти при таком подходе:
Что касается использования памяти, проблема решена! А что касается производительности во время выполнения, решение для потоковой передачи/обработки фрагментов с ijson на самом деле работает немного быстрее, хотя это не обязательно будет иметь место для других наборов данных или алгоритмов.
Другие подходы
Как всегда, есть и другие решения, которые вы можете попробовать:
- Pandas: Pandas может читать JSON, и теоретически он может делать это более эффективно с точки зрения использования памяти для определенных макетов JSON. На практике, по крайней мере, для этого примера пиковая память была намного хуже — 287 МБ, не считая накладных расходов на импорт Pandas.
- SQLite: база данных SQLite может анализировать JSON, хранить JSON в столбцах и запрашивать JSON (см. документацию).Таким образом, можно загрузить JSON в файл базы данных на диске и выполнить запросы к нему, чтобы извлечь только соответствующее подмножество данных. Я не измерял этот подход, но если вам нужно выполнить несколько запросов к одному и тому же файлу JSON, это может быть хорошим путем в будущем; вы также можете добавить индексы.
Наконец, если у вас есть контроль над выходным форматом, есть способы уменьшить использование памяти при обработке JSON, переключившись на более эффективное представление. Например, переход от одного гигантского списка объектов JSON к записи JSON в каждой строке означает, что каждая декодированная запись JSON будет использовать лишь небольшой объем памяти.
Узнайте еще больше о способах сокращения использования памяти — прочтите остальную часть руководства по наборам данных, превышающим объем памяти, для Python.
Тратить время и деньги на процессы, использующие слишком много памяти?
Ваш пакетный процесс Python использует слишком много памяти, и вы понятия не имеете, какая часть вашего кода отвечает за это.
Вам нужен инструмент, который точно подскажет, на чем следует сосредоточить усилия по оптимизации, инструмент, разработанный для специалистов по обработке и анализу данных. Узнайте, чем может помочь профилировщик памяти Fil.
Как вы обрабатываете большие наборы данных с ограниченным объемом памяти?
Получите бесплатную памятку, в которой рассказывается, как обрабатывать большие объемы данных с ограниченным объемом памяти с помощью Python, NumPy и Pandas.
Кроме того, примерно каждую неделю вы будете получать новые статьи, в которых рассказывается, как обрабатывать большие данные и, в более общем плане, улучшать свои навыки разработки программного обеспечения, от тестирования до упаковки и повышения производительности:
JSON (обозначение объектов JavaScript) — это популярный способ структурирования данных. Он используется для обмена информацией между веб-приложением и сервером. Но как прочитать файл JSON в Python?
В этой статье я покажу вам, как использовать методы json.loads() и json.load() для разбора и чтения файлов и строк JSON.
Синтаксис JSON
Прежде чем мы приступим к синтаксическому анализу и чтению файла JSON, нам сначала нужно понять основной синтаксис. Синтаксис JSON выглядит как литерал объекта JavaScript с парами ключ-значение.
Это пример данных JSON для freeCodeCamp:
Как анализировать строку JSON в Python
Python имеет встроенный модуль, позволяющий работать с данными JSON. В верхней части файла вам нужно будет импортировать модуль json.
Если вам нужно проанализировать строку JSON, которая возвращает словарь, вы можете использовать метод json.loads().
Как анализировать и читать файл JSON в Python
В этом примере у нас есть файл JSON с именем fcc.json, который содержит те же данные, что и ранее, касающиеся курсов, предлагаемых freeCodeCamp.
Если мы хотим прочитать этот файл, нам сначала нужно использовать встроенную в Python функцию open() с режимом чтения. Мы используем ключевое слово with, чтобы убедиться, что файл правильно закрыт.
Если файл не может быть открыт, мы получим OSError. Это пример «FileNotFoundError», если я ошибаюсь в имени файла fcc.json.
Затем мы можем проанализировать файл с помощью метода json.load() и присвоить его переменной с именем fcc_data .
Последним шагом будет печать результатов.
Вот как будет выглядеть весь код:
Как правильно печатать данные JSON в Python
Если мы изучим напечатанные данные, то увидим, что все данные JSON печатаются в одной строке.
Но это может быть трудно читать. Чтобы это исправить, мы можем использовать метод json.dumps() с параметром indent .
В этом примере у нас будет отступ в 4 пробела, и мы будем печатать данные в более удобном для чтения формате.
Мы также можем отсортировать ключи в алфавитном порядке, используя параметр sort_keys и установив для него значение True .
Заключение
JSON (JavaScript Object Notation) — это популярный способ структурирования данных, который используется для обмена информацией между веб-приложением и сервером.
Если вам нужно проанализировать строку JSON, которая возвращает словарь, вы можете использовать метод json.loads().
Если вам нужно проанализировать файл JSON, который возвращает словарь, вы можете использовать метод json.load().
Я музыкант и программист.
Если вы дочитали до этого места, отправьте твит автору, чтобы показать, что вам не все равно. Твитнуть спасибо
Научитесь программировать бесплатно. Учебная программа freeCodeCamp с открытым исходным кодом помогла более чем 40 000 человек получить работу в качестве разработчиков. Начать
freeCodeCamp – это поддерживаемая донорами некоммерческая организация, освобожденная от налогов в соответствии со статьей 501(c)(3) (идентификационный номер федерального налогоплательщика США: 82-0779546)
Наша миссия: помочь людям научиться программировать бесплатно. Мы достигаем этого, создавая тысячи видеороликов, статей и интерактивных уроков по кодированию — все они находятся в свободном доступе. У нас также есть тысячи учебных групп freeCodeCamp по всему миру.
Пожертвования в пользу freeCodeCamp идут на наши образовательные инициативы и помогают оплачивать серверы, услуги и персонал.
В этом руководстве мы рассмотрим, как читать и записывать данные JSON из файла и в файл в Python с помощью модуля json.
JSON (JavaScript Object Notation) – чрезвычайно популярный формат для сериализации данных, учитывая его универсальность и легкость, а также удобство для человека. В частности, он широко используется в мире веб-разработки, где вы, вероятно, столкнетесь с сериализованными объектами JSON, отправляемыми из REST API, конфигурацией приложения или даже простым хранилищем данных.
Учитывая его распространенность, чтение и анализ файлов JSON (или строк) довольно распространены, и запись JSON для отправки не менее распространена. В этом руководстве мы рассмотрим, как использовать модуль json для чтения и записи JSON в Python.
Запись JSON в файл с помощью Python
Естественный формат JSON похож на карту в информатике — карту пар ключ-значение. В Python словарь является реализацией карты, поэтому мы, естественно, сможем точно представлять JSON с помощью словаря.
Словарь может содержать другие вложенные словари, массивы, логические значения или другие примитивные типы, такие как целые числа и строки.
Встроенный пакет json предлагает несколько удобных методов, которые позволяют нам выполнять преобразование между JSON и словарями.
При этом давайте импортируем модуль json, определим словарь с некоторыми данными, а затем преобразуем его в JSON перед сохранением в файл:
В результате:
Здесь у нас есть простой словарь с несколькими сотрудниками, у каждого из которых есть имя, отдел и место. Функция dumps() модуля json выгружает словарь в содержимое JSON и возвращает строку JSON.
После сериализации вы можете решить отправить его в другую службу, которая его десериализует или, скажем, сохранит. Чтобы сохранить эту строку JSON в файле, мы просто откроем файл в режиме записи и запишем его. Если вы не хотите извлекать данные в независимую переменную для последующего использования, а хотите просто выгрузить их в файл, вы можете пропустить функцию dumps() и использовать вместо нее dump():
Любой файлоподобный объект может быть передан второму аргументу функции dump(), даже если это не настоящий файл. Хорошим примером этого может быть сокет, который можно открывать, закрывать и записывать в него так же, как в файл.
Чтение JSON из файла с помощью Python
Сопоставление между содержимым словаря и строкой JSON является простым, поэтому их легко преобразовать. Как и json.dumps(), функция json.loads() принимает строку JSON и преобразует ее в словарь.
Кроме того, json.load() позволяет загружать файл.
В результате:
В качестве альтернативы давайте прочитаем строку JSON в словарь:
Что также приводит к:
Это особенно полезно для анализа ответов REST API, которые отправляют JSON. Эти данные поступают к вам в виде строки, которую вы затем можете напрямую передать в json.loads(), и у вас есть гораздо более удобный словарь для работы!
Параметры
При сериализации данных в JSON с помощью Python результат будет в стандартном формате и не очень удобочитаемым, так как пробелы удалены. Хотя это идеальное поведение для передачи данных (компьютеры не заботятся о удобочитаемости, но заботятся о размере), иногда вам может потребоваться внести небольшие изменения, например добавить пробелы, чтобы сделать их удобочитаемыми для человека.
json.dump() / json.dumps() и json.load() / json.loads() предоставляют несколько вариантов форматирования.
Красивая печать JSON
Сделать JSON понятным для человека (т. е. "красивая печать") так же просто, как передать целочисленное значение для параметра отступа:
Бесплатная электронная книга: Git Essentials
Ознакомьтесь с нашим практическим руководством по изучению Git, включающим передовые практики, общепринятые стандарты и памятку. Перестаньте гуглить команды Git и на самом деле изучите их!
Это создает гораздо более читаемый вывод с 4 пробелами на каждом отступе:
Еще один вариант — использовать инструмент командной строки — json.tool . Итак, если вы просто хотите красиво напечатать JSON в командной строке, вы можете сделать что-то вроде этого:
Сортировка
Объект JSON — это:
"Объект представляет собой неупорядоченный набор пар имя/значение."
Порядок клавиш не гарантируется, но возможно, вам потребуется принудительно применить порядок клавиш. Чтобы добиться упорядочения, вы можете передать значение true для параметра sort_keys при использовании json.dump() или json.dumps():
В результате:
Текст ASCII
По умолчанию json.dump() и json.dumps() гарантируют, что текст в заданном словаре Python будет закодирован в ASCII. Если присутствуют символы, отличные от ASCII, они автоматически экранируются, как показано в следующем примере:
Это не всегда приемлемо, и во многих случаях вы можете не трогать символы Unicode. Для этого установите для параметра sure_ascii значение False :
Заключение
В этом руководстве мы познакомили вас с методами json.dump() , json.dumps() , json.load() и json.loads(), которые помогают сериализовать и десериализовать строки JSON.
Поскольку JSON является одним из самых популярных способов сериализации структурированных данных, вам, вероятно, придется взаимодействовать с ним довольно часто, особенно при работе с веб-приложениями. Модуль Python json — отличный способ начать работу, хотя вы, вероятно, обнаружите, что simplejson — еще одна отличная альтернатива, гораздо менее строгая к синтаксису JSON.
JSON – это текст, записанный с использованием объектной нотации JavaScript.
JSON в Python
В Python есть встроенный пакет json , который можно использовать для работы с данными JSON.
Пример
Импортируйте модуль json:
Синтаксический анализ JSON — преобразование из JSON в Python
Если у вас есть строка JSON, вы можете проанализировать ее с помощью метода json.loads().
Результатом будет словарь Python.
Пример
Преобразование из JSON в Python:
Преобразование из Python в JSON
Если у вас есть объект Python, вы можете преобразовать его в строку JSON с помощью метода json.dumps().
Пример
Преобразование из Python в JSON:
Вы можете преобразовывать объекты Python следующих типов в строки JSON:
Пример
Преобразуйте объекты Python в строки JSON и распечатайте значения:
print(json.dumps())
print(json.dumps(["яблоко", "бананы"]))
print(json.dumps(("яблоко", "бананы" )))
print(json.dumps("hello"))
print(json.dumps(42))
print(json.dumps(31.76))
print( json.dumps(True))
print(json.dumps(False))
print(json.dumps(None))
При преобразовании из Python в JSON объекты Python преобразуются в эквивалент JSON (JavaScript):
Python | JSON |
---|---|
dict | Object | tr>
список | Массив |
кортеж | Массив |
str | String |
int | Число |
float | Число |
True | true |
False | false |
Нет | null |
Пример
Преобразовать объект Python, содержащий все допустимые типы данных:
Отформатировать результат
В приведенном выше примере печатается строка JSON, но ее не очень легко читать, нет отступов и разрывов строк.
Метод json.dumps() имеет параметры, облегчающие чтение результата:
Пример
Используйте параметр indent для определения количества отступов:
Вы также можете определить разделители, значение по умолчанию (", ", ":"), что означает использование запятой и пробела для разделения каждого объекта, а также двоеточие и пробел для отделения ключей от значений: р>
Пример
Используйте параметр separators, чтобы изменить разделитель по умолчанию:
Заказать результат
Метод json.dumps() имеет параметры для упорядочения ключей в результате:
Пример
Используйте параметр sort_keys, чтобы указать, должен ли результат сортироваться или нет:
Читайте также: