2016-11-28 3 views
1

У меня есть действительно большой словарь с 4 миллионами ключей, которые я получаю после чтения в большом текстовом файле. Мне нужно, чтобы мой скрипт работал быстрее, и теперь я ищу подходящий способ сделать это. Я пытаюсь сохранить словарь где-нибудь, чтобы получить более быстрый доступ к нему, но использование pickle фактически снижает мою скорость до 150 секунд для простое чтение! Чтение в текстовом файле происходит намного быстрее, что кажется действительно странным. Я также попытался сохранить его в базе данных с помощью sqlite, но это тоже заняло слишком много времени. Как обычно такая проблема решена?Самый быстрый способ загрузки в словаре

+1

Как вы загружаете его сейчас? Как словарь хранится в файле? Если это действительный JSON, то использование json.load python, вероятно, будет самым быстрым, что вы можете это сделать ... Также обратите внимание, что другие форматы, такие как 'msgpack', также могут быть хорошим кандидатом ... – mgilson

+0

сейчас я просто получил текстовый файл с парами ключ-значение, разделенный пробелами в каждой строке. – EliteKaffee

+0

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

ответ

0

Если вы используете python2, я рекомендую использовать wiredtiger в качестве быстрого хранилища ключей/значений. Я рекомендую использовать ветку wiredtiger. При условии, вы swig3 и python2-DEV установлен на вашей системе, можно сделать следующие установки wiredtiger:

git clone https://github.com/wiredtiger/wiredtiger --branch=develop 
cd wiredtiger 
./autogen.sh && ./configure --enable-python && make && make install 

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

from wiredtiger import wiredtiger_open 


WT_NOT_FOUND = -31803 


class KV(object): 

    def __init__(self, path): 
     # init wiredtiger 
     self._wiredtiger = wiredtiger_open(path, 'create') 
     self.session = self._wiredtiger.open_session() 
     # create key/value table 
     self.session.create('table:kv', 'key_format=S,value_format=S') 
     self.kv = self.session.open_cursor('table:kv') 

    def close(self): 
     self._wiredtiger.close() 

    def __setitem__(self, key, value): 
     self.kv.set_key(key) 
     self.kv.set_value(value) 
     self.kv.insert() 

    def __getitem__(self, key): 
     self.kv.set_key(key) 
     if self.kv.search() == WT_NOT_FOUND: 
      msg = "key '%s' not found" % key 
      raise KeyError(msg) 
     else: 
      return self.kv.get_value() 


kv = KV('./data') 
kv['foo'] = 'bar' 
assert kv['foo'] == 'bar' 

Если использование wiredtiger затруднительно, вы можете попробовать leveldb с помощью plyvel bindings. API очень прост, но он намного медленнее.

Использование plyvel вы можете сделать следующее:

import plyvel 

db = plyvel.DB('/tmp/testdb/', create_if_missing=True) 
db.put('key', 'value') 
# later 
assert db.get('key') == 'value' 

В противном случае, если вы используете python2 есть builtin shelve module.

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