如何无需加载全部数据到内存,直接写入Python字典到Pickle文件?
问题解答
直接说结论:没法像操作字典那样直接往Pickle文件里逐键值写入——因为Pickle的机制是把完整的Python对象序列化后写入文件,不能对已生成的Pickle文件做增量式的字典键值修改或追加。不过有两种实用的替代方案,既能避免把全量数据塞进内存,又能实现你的需求:
方案1:用Pickle增量写入键值对,读取时再组装字典
这种方式是把每个键值对作为单独的元组写入Pickle文件,读取时可以逐个加载,要么按需处理,要么组装成字典。适合必须用Pickle格式,且读取时也不想一次性加载所有数据的场景。
写入代码(修正了你的gzip使用问题):
import gzip import pickle # 用gzip.open正确打开压缩文件 with gzip.open("output.kv.pkl.gz", "wb") as f_out: with open("table.tsv", "r") as f_in: for line in f_in: line = line.strip() if not line: continue fields = line.split("\t") k = fields[3] v = fields[1] # 把键值对打包成元组,逐个序列化写入 pickle.dump((k, v), f_out)
读取代码
如果需要重建完整字典:
import gzip import pickle result_dict = {} with gzip.open("output.kv.pkl.gz", "rb") as f_in: while True: try: k, v = pickle.load(f_in) result_dict[k] = v except EOFError: break # 读到文件结尾就停止
如果不需要全量加载,只想按需读取部分数据:
import gzip import pickle with gzip.open("output.kv.pkl.gz", "rb") as f_in: for _ in range(10): # 比如只读取前10个键值对 try: k, v = pickle.load(f_in) print(k, v) except EOFError: break
方案2:用shelve模块(推荐)
shelve是Python标准库专门用来做字典持久化的工具,底层基于Pickle,用法和普通字典几乎一模一样——你可以直接像操作字典那样赋值键值对,数据会自动写到磁盘,不会把全量数据加载到内存里。
写入代码:
import shelve # 打开shelve数据库文件,操作完会自动关闭 with shelve.open("output_dict") as db: with open("table.tsv", "r") as f_in: for line in f_in: line = line.strip() if not line: continue fields = line.split("\t") k = fields[3] v = fields[1] db[k] = v # 直接像字典一样赋值,自动持久化到磁盘
读取代码:
import shelve with shelve.open("output_dict") as db: # 按键取值,和字典用法完全一致 print(db.get("target_key")) # 遍历所有键值对,不会一次性把所有数据加载到内存 for k, v in db.items(): print(k, v)
可选:压缩shelve文件
shelve默认生成多个文件(.dat、.dir、.bak),如果需要压缩节省空间,可以用shutil打包:
import shutil # 把shelve文件打包成gzip压缩包 shutil.make_archive("output_dict", "gztar", ".", "output_dict")
额外说明
如果你的需求是必须生成单个Pickle格式的字典对象,那没办法绕开“先把所有数据加载到内存构建字典,再序列化写入”——因为Pickle只能序列化完整的对象。这种情况下如果内存不够,只能考虑分块处理或者换用其他存储格式(比如JSON逐行写入,但JSON也没法直接生成字典对象的增量写入)。
内容的提问来源于stack exchange,提问作者O.rka
相关产品推荐
相关产品推荐

