Компиляция в байтовый код занимает слишком много памяти

Мне нужно импортировать очень большой словарь в python, и я сталкиваюсь с некоторыми неожиданными узкими местами памяти. Словарь имеет форму,

d = {(1,2,3):(1,2,3,4), (2,5,6)=(4,2,3,4,5,6), ... } 

Таким образом, каждый ключ представляет собой 3-кортеж, и каждое значение представляет собой относительно небольшой набор произвольного размера (вероятно, не более 30 элементов). То, что делает словарь большим, – это количество ключей. Меньший пример того, с чем я работаю, имеет примерно 247257 ключей. Я создаю этот словарь с помощью моделирования, поэтому я могу написать текстовый файл, который определяет этот словарь, и для примера, который я только что упомянул, это файл размером 94 МБ. Узкое место, с которым я столкнулся, заключается в том, что исходный компилятор для байтового кода на основе python потребляет около 14 ГБ оперативной памяти. Поэтому, в первый раз, когда я импортирую словарь, я вижу, что объем использования памяти увеличивается, и через 10 секунд все загружается. Если файл .pyc уже создан, импорт почти мгновен. Используя pympler, я решил, что этот словарь содержит всего около 200 МБ в памяти. Какая сделка здесь? Есть ли у меня какие-либо другие варианты того, как этот словарь загружается в python или, по крайней мере, скомпилирован в байтовый код. Я запускаю генераторные симуляции на C ++, и я не могу писать файлы в любом формате, в котором я нуждаюсь. Есть ли там какие-либо варианты (библиотеки python и т. Д.)? Я взаимодействую с некоторым программным обеспечением, которое нуждается в этих данных в качестве словаря, поэтому, пожалуйста, никаких других предложений в этой области. Также на всякий случай, когда вам интересно, я определил словарь в текстовом файле, как указано выше, так же, как и так,

 d = {} d[1,2,3] = (1,2,3,4) d[2,5,6] = (4,2,3,4,5,6) ... 

Оба дают одинаковый всплеск памяти при компиляции в байтовый код. На самом деле, второй, кажется, немного хуже, что удивительно для меня. Должен быть какой-то способ укротить количество ram, необходимое для первоначального компиляции. Кажется, он должен каким-то образом выполнить компиляцию одной пары ключ-значение за раз. Есть идеи?

Дополнительная информация: использование python 2.6.5

7 Solutions collect form web for “Компиляция в байтовый код занимает слишком много памяти”

Я предполагаю, что ваш большой компиляционный всплеск происходит, когда вы делаете «import module_containing_humungous_dict_statement». Тогда не имеет значения, есть ли у вас только один оператор или 247257 отдельных операторов присваивания, весь модуль все равно будет скомпилирован сразу. Вы можете попробовать использовать форму для отдельного присваивания, а затем открыть файл, считая по одной строке за раз, и выполнить его. Затем вы будете составлять только одну строку за раз. Вероятно, потребуется некоторое время.

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

Вы пытались хранить данные в отдельном файле в следующем формате, а затем динамически загружать его в python?

 1,2,3=1,2,3 2,5,6=4,2,3,4,5,6 

Сценарий Python должен выглядеть примерно так:

 file = open("filename") d = {} for line in file: key, val = line.split("=") key = tuple(key.split(",")) d[key] = tuple(val.split(",")) file.close() 

Я подозреваю, что создание списка для использования в качестве ключа – это то, что дорого. Определите функцию, которая принимает три части тройки в качестве входных данных и возвращает строку с ограничением на канал. Используйте это как свой ключ.

Как я читаю ваш вопрос, вы генерируете исходный код Python в своем симуляторе, а сгенерированный источник содержит содержимое гигантского словаря с жестким кодированием. Если это так, то вы можете легко сгенерировать это:

 def giantdict(): d0 = {(1, 2): (3, 4), (3, 4): (5, 6), ...} # first 1000 key/value pairs here d1 = {(1, 2): (3, 4), (3, 4): (5, 6), ...} # next 1000 key/value pairs d2 = {(1, 2): (3, 4), (3, 4): (5, 6), ...} # next 1000 key/value pairs d3 = {(1, 2): (3, 4), (3, 4): (5, 6), ...} # next 1000 key/value pairs # ... until you're done bigd = d0 bigd.update(d1) del d1 bigd.update(d2) del d2 # ... continue updating with all the dN dictionaries return bigd 

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

Хотя этот вид кода (мой или ваш) привлечет мою ярость и гнев, если человек написал это, я не вижу необходимости, чтобы сгенерированный код был «хорошим», если вы знаете, что человеку никогда не понадобится его читать или сохранить его.

Вот класс, который использует defaultdict для автоматической вложенности индексированных значений, с некоторыми специальными __getitem__ и __setitem__ для принятия кортежей в качестве аргументов:

 from collections import defaultdict defdict3level = (lambda : defaultdict(lambda : defaultdict( lambda : defaultdict(tuple)))) class dict3level(object): def __init__(self): self.defdict = defdict3level() def __getitem__(self, key): if isinstance(key, tuple): if len(key)==3: return self.defdict[key[0]][key[1]][key[2]] elif len(key)==2: return self.defdict[key[0]][key[1]] elif len(key)==1: return self.defdict[key[0]] else: return self.defdict[key] def __setitem__(self, key, value): if isinstance(key, tuple) and len(key)==3: self.defdict[key[0]][key[1]][key[2]] = value else: self.defdict[key] = value def __getattr__(self, attr): return getattr(self.defdict, attr) 

Теперь выполните все ваши задания, как раньше:

 d = dict3level() d[1,2,3] = (1,2,3,4) d[1,2,7] = (3,4,5,6) d[2,5,6] = (4,2,3,4,5,6) 

Вы можете получить определенную запись для определенного кортежа:

 # get a specific entry print d[1,2,3] 

Но вы также можете перемещаться по своему типу по уровням:

 # get all different 0'th index values print d.keys() # get all sub values in d[1,2,*] print d[1,2].keys() for key in d[1,2]: print "d[1,2,%d] = %s" % (key, d[1,2][key]) # no such entry, return empty tuple print d[1,2,0] 

дает:

 print d[1,2,3] -> (1, 2, 3, 4) print d.keys() -> [1, 2] print d[1,2].keys() -> [3, 7] for key in d[1,2]:... -> d[1,2,3] = (1, 2, 3, 4) d[1,2,7] = (3, 4, 5, 6) print d[1,2,0] -> () 

(Не знаю, как это повлияет на ваши проблемы с памятью и / или травлением, но в результате структура имеет гораздо больше возможностей для этого.)

  • Как преобразовать строго отсортированный список строк в dict?
  • Добавить ключи в словаре в порядке SORTED
  • Python: list () в качестве значения по умолчанию для словаря
  • Структура Matlab в Python
  • Проверка эквивалентности двух Массивных словарей Python
  • Python эквивалент zip для словарей
  • Поиск Hashtable / dictionary / map с регулярными выражениями
  • Python обратное / обратное отображение (но с несколькими значениями для каждого ключа)
  • Python Django: лучше ли добавлять свойства к объекту или делать словарь данных?
  • Перегрузка динамического оператора на классы dict в Python
  • Инициализация словаря в python с ключом и отсутствие соответствующих значений
  •  
    Interesting Posts for Van-Lav

    Предупреждение pep8 для строки регулярного выражения в Python, Eclipse

    Как я могу избежать преобразования python больших чисел в научную нотацию?

    «Невозможно открыть файл include:« config-win.h »: нет такого файла или каталога» при установке mysql-python

    Python – понимание функции отправки генератора

    Как получить доступ к определенному start_url в Scroll CrawlSpider?

    Учетные данные по умолчанию для App Engine перестали работать на локальном сервере dev

    Как изменить ось y импортированного изображения в Tkinter?

    Поворот тиковых меток для морского баржета

    как подождать, пока один раскрывающийся список будет обработан, прежде чем перейти к следующему?

    События мыши в WxPython TaskBarIcon на Mac OSX не запускаются

    Подпроцесс Python check_output намного медленнее, чем вызов

    Список процессов в Linux через Python

    Как разобрать один файл, используя привязки Python к Clang?

    Используются ли обычно docstrings атрибуты python?

    Многократное повторение ключевого слова `in`

    Python - лучший язык программирования в мире.