2016-11-03 3 views
1

Python (и spyder) возвращает MemoryError при загрузке файла JSON размером 500Mo.MemoryError при загрузке файла JSON

Но мой компьютер имеет 32Go RAM и «память», отображаемая шпионом, с 15% до 19%, когда я пытаюсь загрузить его! Кажется, что у меня будет гораздо больше пространства ...

Что-то я не думал?

+0

какая ОС вы используете? – Alex

+0

Windows 10, и я использую Spyder для кодирования и выполнения. –

+0

Если вы используете x32 python, вы ограничены объемом 4 ГБ на каждый процесс. Вероятно, вы достигли этого предела. – Alex

ответ

5

500 МБ данных JSON не приводит к использованию 500 МБ памяти. Это приведет к кратности этого. Именно по тому, какой фактор зависит от данных, но коэффициент 10-25 не является чем-то необычным.

Например, следующий простой JSON строка из 14 символов (байтов на диске) приводит объект Python почти в 25 раз больше (Python 3.6b3):

>>> import json 
>>> from sys import getsizeof 
>>> j = '{"foo": "bar"}' 
>>> len(j) 
14 
>>> p = json.loads(j) 
>>> getsizeof(p) + sum(getsizeof(k) + getsizeof(v) for k, v in p.items()) 
344 
>>> 344/14 
24.571428571428573 

Это потому, что объекты Python требуют некоторые накладные расходы ; экземпляры отслеживают количество ссылок на них, тип их и их атрибуты (если тип поддерживает атрибуты) или их содержимое (в случае контейнеров).

Если вы используете json встроенную библиотеку, чтобы загрузить этот файл, он будет строить большие и большие объекты содержимого, как они обрабатываются, и в какой-то момент операционная система будет отказывать в предоставлении более Память. Это не будет на 32 ГБ, потому что есть ограничение за процесс сколько памяти можно использовать, поэтому вероятность того, что будет 4 ГБ. В этот момент все те объекты, которые уже созданы, снова освобождаются, поэтому в конечном итоге фактическое использование памяти не должно сильно измениться.

Решение состоит в том, чтобы разбить этот большой файл JSON на более мелкие подмножества или использовать парсер JSON, управляемый событиями, например ijson.

Парсер JSON, управляемый событиями, не создает объекты Python для всего файла, только для текущего обработанного элемента, и уведомляет ваш код для каждого элемента, который он создал с событием (например, «запуск массива» string, теперь начиная отображение, это конец отображения и т. д.). Затем вы можете решить, какие данные вам нужны, и что следует игнорировать. Все, что вы игнорируете, снова отбрасывается, а использование памяти остается низким.

+0

Percect ответ, как всегда от вас;) Для другого я добавляю ссылку на объяснение того, как работает ijson: http://stackoverflow.com/ Вопросы/40330820/load-an-element-with-python-from-large-json-file –

+0

И есть ли способ изменить предельную память на каждый процесс? –

+0

@ AgapeGal'lo: Я не уверен, что вы можете, мне кажется, что в Windows вы можете только * уменьшить * пределы: [Установить ограничение памяти для Windows (или пользователя)] (// stackoverflow.com/q/192876). Я сильно сомневаюсь, что это сработает для вас. –

1

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

Таким образом, важная информация заключается в том, что окна ограничивают объем памяти на процесс до 2 или 4 ГБ, в зависимости от того, какие окна вы используете (32 или 64). Если вы используете pythonxy, то это будет 2 ГБ (он существует только в 32). Во всяком случае, в обоих направлениях это очень мало!

Я решил эту проблему, установив виртуальный Linux в свои окна, и он работает.Вот основной шаг, чтобы сделать это:

  1. Установите Virtual Box
  2. Установка Ubuntu (for exemple)
  3. Установить питона для ученого на вашем компьютере, like SciPy
  4. Создание файла для совместного использования между «компьютерами» 2 (вы найти учебник по Google)
  5. Выполнить код на вашем убунту «компьютерные»: это sould работу;)

NB: Не забудьте предоставить достаточный объем оперативной памяти и памяти виртуальному компьютеру.

Это работает для меня. У меня больше нет этой проблемы с «ошибкой памяти».

Я размещаю здесь этот asnwer от there.

Смежные вопросы