Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

Да. 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

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

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

Ответ 2

Если вы хотите, чтобы модуль был более надежным, чем 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 - это dict в памяти, а 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:[email protected]/foo'.
    For postgresql, use database='postgresql://user:[email protected]/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