[英]Fastest way to store large files in Python
我最近問了一個關於如何將大型python對象保存到文件的問題。 我以前遇到過將大量Python字典轉換為字符串並通過write()
將它們write()
文件的問題。 現在我正在使用泡菜。 雖然它可以工作,但文件非常大(> 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)實現的壓縮率。
在實現數據序列化時,Python代碼會非常慢。 如果你嘗試在純Python中創建一個與Pickle等價的東西,你會發現它會超級慢。 幸運的是,執行該功能的內置模塊非常好。
除了cPickle
之外,你會發現marshal
模塊,速度要快得多。 但它需要一個真正的文件句柄(而不是來自類文件對象)。 您可以import marshal as Pickle
並查看差異。 我不認為你可以制作比這更快的自定義序列化器......
這是Python序列化程序的實際(不是那么老) 嚴肅的基准
我只想擴展phihag的答案。
當嘗試序列化接近RAM大小的對象時, 應該避免使用pickle / cPickle ,因為它需要額外的內存,大小是對象大小的1-2倍才能序列化。 即使將其流式傳輸到BZ2File也是如此。 在我的情況下,我甚至耗盡了交換空間。
但是JSON的問題(以及與鏈接文章中提到的HDF文件類似)是它無法序列化元組,這在我的數據中用作dicts的鍵。 對此沒有很好的解決方案; 我能找到的最好的方法是將元組轉換為字符串,這需要一些自己的內存,但要比pickle少得多。 如今,您還可以使用ujson庫 ,它比json庫快得多。
對於由字符串組成的元組(要求字符串不包含逗號):
import 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()])
這種方法相對於泡菜的另一個優點是,當使用bzip2壓縮時,json似乎比泡菜更好地壓縮。
更快,甚至可能在[寫作]之前壓縮這個pickle文件
當然這是可能的,但沒有理由在編寫它之前嘗試在內存中創建一個顯式的壓縮副本(它可能不適合!),當你可以自動使它在編寫時壓縮,內置標准庫功能 ;)
見http://docs.python.org/library/gzip.html 。 基本上,你用它創建一種特殊的流
gzip.GzipFile("output file name", "wb")
然后使用它就像使用open(...)
(或file(...)
創建的普通file
一樣)。
看看谷歌的ProtoBuffers 。 雖然它們並非設計用於開箱即用的大型文件,如音頻 - 視頻文件,但它們可以很好地處理對象序列化,因為它們是為它設計的。 實踐表明,有一天您可能需要更新文件的結構,ProtoBuffers將處理它。 此外,它們還針對壓縮和速度進行了高度優化。 而且你不依賴於Python,Java和C ++都得到了很好的支持。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.