Рассол против полки, хранящей большие словари в Python

Если я храню большой каталог как pickle файл, загружает его через cPickle Значит, все это будет сразу занято в память?

Если это так, есть ли кроссплатформенный способ получить что-то вроде pickle, но получить доступ к каждой записи по одному ключу на элементе (т.е. избегать загрузки всего словаря в память и загружать только каждую запись по имени)? я знаю shelve должен сделать это: это так же портативно, как pickle хоть?

2 ответа

Решение

Я знаю, что шельф должен делать это: это так же портативно, как рассол?

Да. shelve является частью стандартной библиотеки Python и написана на Python.

редактировать

Так что, если у вас есть большой словарь:

bigd = {'a': 1, 'b':2, # . . .
}

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

import shelve

myShelve = shelve.open('my.shelve')
myShelve.update(bigd)
myShelve.close()

Тогда позже вы можете:

import shelve

myShelve = shelve.open('my.shelve')
value = myShelve['a']
value += 1
myShelve['a'] = value

Вы в основном относитесь к объекту полки как к диктату, но элементы хранятся на диске (как отдельные соленья) и считываются по мере необходимости.

Если ваши объекты могут храниться в виде списка свойств, то sqlite может быть хорошей альтернативой. Полки и соленья удобны, но доступны только для Python, но базу данных sqlite можно читать с большинства языков.

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

Здесь мы сначала создаем некоторые маринованные объекты, хранящиеся на диске. Они используют dir_archive, который хранит один объект на файл.

>>> d = dict(zip('abcde',range(5)))
>>> d['f'] = max
>>> d['g'] = lambda x:x**2
>>> 
>>> import klepto
>>> help(klepto.archives.dir_archive)       

>>> print klepto.archives.dir_archive.__new__.__doc__
initialize a dictionary with a file-folder archive backend

    Inputs:
        name: name of the root archive directory [default: memo]
        dict: initial dictionary to seed the archive
        cached: if True, use an in-memory cache interface to the archive
        serialized: if True, pickle file contents; otherwise save python objects
        compression: compression level (0 to 9) [default: 0 (no compression)]
        memmode: access mode for files, one of {None, 'r+', 'r', 'w+', 'c'}
        memsize: approximate size (in MB) of cache for in-memory compression

>>> a = klepto.archives.dir_archive(dict=d)
>>> a
dir_archive('memo', {'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': <function <lambda> at 0x102f562a8>, 'f': <built-in function max>}, cached=True)
>>> a.dump()
>>> del a

Теперь все данные на диске, давайте выберем, какие из них мы хотим загрузить в память. b это память в памяти, в то время как b.archive сопоставляет коллекцию файлов в виде словаря.

>>> b = klepto.archives.dir_archive('memo')
>>> b
dir_archive('memo', {}, cached=True)
>>> b.keys()   
[]
>>> b.archive.keys()
['a', 'c', 'b', 'e', 'd', 'g', 'f']
>>> b.load('a')
>>> b
dir_archive('memo', {'a': 0}, cached=True)
>>> b.load('b')
>>> b.load('f')
>>> b.load('g')
>>> b['g'](b['f'](b['a'],b['b']))
1

klepto также обеспечивает тот же интерфейс к sql архив.

>>> print klepto.archives.sql_archive.__new__.__doc__
initialize a dictionary with a sql database archive backend

    Connect to an existing database, or initialize a new database, at the
    selected database url. For example, to use a sqlite database 'foo.db'
    in the current directory, database='sqlite:///foo.db'. To use a mysql
    database 'foo' on localhost, database='mysql://user:pass@localhost/foo'.
    For postgresql, use database='postgresql://user:pass@localhost/foo'. 
    When connecting to sqlite, the default database is ':memory:'; otherwise,
    the default database is 'defaultdb'. If sqlalchemy is not installed,
    storable values are limited to strings, integers, floats, and other
    basic objects. If sqlalchemy is installed, additional keyword options
    can provide database configuration, such as connection pooling.
    To use a mysql or postgresql database, sqlalchemy must be installed.

    Inputs:
        name: url for the sql database [default: (see note above)]
        dict: initial dictionary to seed the archive
        cached: if True, use an in-memory cache interface to the archive
        serialized: if True, pickle table contents; otherwise cast as strings

>>> c = klepto.archives.sql_archive('database')
>>> c.update(b)
>>> c
sql_archive('sqlite:///database', {'a': 0, 'b': 1, 'g': <function <lambda> at 0x10446b1b8>, 'f': <built-in function max>}, cached=True)
>>> c.dump()

Где сейчас те же объекты на диске и в архиве sql. Мы можем добавить новые объекты в любой архив.

>>> b['x'] = 69
>>> c['y'] = 96
>>> b.dump('x')
>>> c.dump('y')

Получить klepto здесь: https://github.com/uqfoundation

Другие вопросы по тегам