24

如果我将一个大目录存储为一个pickle文件,通过加载它是否cPickle意味着它会一次全部消耗到内存中?

如果是这样,是否有一种跨平台的方式来获得类似的东西pickle,但是在一个项目上访问每个条目的一个键(即避免将所有字典加载到内存中并且只按名称加载每个条目)?我知道shelve应该这样做:它是否像便携式一样pickle

4

2 回答 2

24

我知道 shelve 应该这样做:它像泡菜一样便携吗?

是的。shelvePython 标准库的一部分,是用 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 数据库可以从大多数语言中读取。

于 2013-02-03T02:07:01.793 回答
8

如果您想要一个比 更健壮的模块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

kleptosql还为存档提供相同的接口。

>>> 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

于 2015-09-15T13:09:24.057 回答