Python - запись большого массива JSON в файл - PullRequest
0 голосов
/ 02 сентября 2018

Я работаю над процессом, который, вероятно, в конечном итоге попытается сериализовать очень большие массивы json в файл. Таким образом, загрузка всего массива в память и простой вывод в файл не будут работать. Мне нужно передавать отдельные элементы в файл, чтобы избежать проблем с нехваткой памяти.

Удивительно, но я не могу найти никаких примеров того, как это сделать. Ниже приведен фрагмент кода, который я собрал вместе. Есть ли лучший способ сделать это?

first_item = True
with open('big_json_array.json', 'w') as out:
     out.write('[')
     for item in some_very_big_iterator:
          if first_item:
               out.write(json.dumps(item))
               first_item = False
          else:
               out.write("," + json.dumps(item))
     out.write("]")

1 Ответ

0 голосов
/ 02 сентября 2018

Хотя ваш код является разумным, его можно улучшить. У вас есть два разумных варианта и дополнительное предложение.

Ваши варианты:

  • Не для генерации массива, а для генерации JSON Lines выходных данных. Для каждого элемента в вашем генераторе это записывает в файл один действительный документ JSON без символов новой строки , за которым следует новая строка. Это легко создать с помощью конфигурации json.dump(item, out) по умолчанию, за которой следует `out.write ('\ n'). Вы получите файл с отдельным документом JSON в каждой строке.

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

    Простое чтение строк JSON, см. Загрузка и анализ файла JSON с несколькими объектами JSON в Python

  • Оберните ваши данные в генераторе и подклассе списка, чтобы json.dump() принял их как список, а затем запишите данные итеративно. Я обрисую это ниже. Учтите, что теперь вам, возможно, придется решить проблему в обратном порядке, прочитав данные JSON снова с Python.

Я предлагаю не использовать JSON здесь. JSON никогда не был предназначен для крупномасштабных наборов данных, это формат обмена данными через Интернет, нацеленный на гораздо меньшую полезную нагрузку. Есть лучшие форматы для такого рода обмена данными. Если вы не можете отклониться от JSON, используйте хотя бы строки JSON.

Вы можете написать массив JSON итеративно, используя генератор и подкласс list, чтобы обмануть библиотеку json и принять ее в виде списка:

class IteratorAsList(list):
    def __init__(self, it):
        self.it = it
    def __iter__(self):
        return self.it
    def __len__(self):
        return 1

with open('big_json_array.json', 'w') as out:
    json.dump(IteratorAsList(some_very_big_iterator), out)

Класс IteratorAsList удовлетворяет двум тестам, которые выполняет кодировщик json: что объект является списком или его подклассом, и что его длина больше 0; когда эти условия будут выполнены, он будет перебирать список (используя __iter__) и кодировать каждый объект.

Функция json.dump() затем записывает данные в файл, поскольку кодер выдает фрагменты данных; он никогда не будет хранить весь вывод в памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...