我最近问了一个问题,关于如何将大型Python对象保存到文件中。我之前遇到过将巨大的Python字典转换为字符串并通过write()
写入文件时出现的问题。现在我正在使用pickle。虽然它可以工作,但文件非常大(> 5 GB)。我在这方面缺乏经验。我想知道在存储到内存之前是否更快或甚至可能对此pickle文件进行压缩。
我最近问了一个问题,关于如何将大型Python对象保存到文件中。我之前遇到过将巨大的Python字典转换为字符串并通过write()
写入文件时出现的问题。现在我正在使用pickle。虽然它可以工作,但文件非常大(> 5 GB)。我在这方面缺乏经验。我想知道在存储到内存之前是否更快或甚至可能对此pickle文件进行压缩。
你可以使用bzip2压缩数据:
from __future__ import with_statement # Only for Python 2.5
import bz2,json,contextlib
hugeData = {'key': {'x': 1, 'y':2}}
with contextlib.closing(bz2.BZ2File('data.json.bz2', 'wb')) as f:
json.dump(hugeData, f)
按照以下方式加载:
from __future__ import with_statement # Only for Python 2.5
import bz2,json,contextlib
with contextlib.closing(bz2.BZ2File('data.json.bz2', 'rb')) as f:
hugeData = json.load(f)
您还可以使用zlib或gzip对数据进行压缩,接口几乎相同。但是,请注意,无论是zlib还是gzip的压缩率都会低于通过bzip2(或lzma)实现的压缩率。
with
语句只是一种语法糖,它确保文件被关闭。你可以将其理解为f = bz2.BZ2File(...)
。这不会在内存中存储大量数据,这是一件好事。数据将会实时序列化和压缩,除了操作系统缓存之外,内存使用量不应该显著大于一个兆字节。 - phihagbz2.BZ2File
是否已经实现了上下文管理接口,就像原生文件被重新改进一样?在这里真的需要使用contextlib.closing
吗? - Karl Knechtelimport ujson as json
from bz2 import BZ2File
bigdata = { ('a','b','c') : 25, ('d','e') : 13 }
bigdata = dict([(','.join(k), v) for k, v in bigdata.viewitems()])
f = BZ2File('filename.json.bz2',mode='wb')
json.dump(bigdata,f)
f.close()
bigdata = dict([(tuple(k.split(',')),v) for k,v in bigdata.viewitems()])
如果您的键是由两个整数组成的2元组,可以采用以下方式:
bigdata2 = { (1,2): 1.2, (2,3): 3.4}
bigdata2 = dict([('%d,%d' % k, v) for k, v in bigdata2.viewitems()])
# ... save, load ...
bigdata2 = dict([(tuple(map(int,k.split(','))),v) for k,v in bigdata2.viewitems()])
相比于 pickle,这种方法的另一个优点是,在使用 bzip2 压缩时,json 可以明显地更好地进行压缩。
gzip.GzipFile("output file name", "wb")
然后像使用普通的open(...)
(或者file(...)
)方法创建文件一样使用它。