You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

合并大体积Pickle字典时内存溢出,Jupyter内核崩溃求助

解决大Pickle字典合并时内存溢出的问题

方法1:逐键写入新文件,避免全量加载

直接用原生pickle模块,先读取第一个字典,逐键值对写入新文件,写完后立即删除原字典释放内存,再处理第二个字典。这种方式内存中仅保留单个键值对和部分文件缓存,大幅降低内存占用。

import pickle

def merge_large_pickles(file1_path, file2_path, output_path):
    # 处理第一个Pickle文件
    with open(file1_path, 'rb') as src_f, open(output_path, 'wb') as dest_f:
        large_dict = pickle.load(src_f)
        for key, value in large_dict.items():
            pickle.dump((key, value), dest_f)
        del large_dict  # 强制释放内存
    
    # 处理第二个Pickle文件(追加写入)
    with open(file2_path, 'rb') as src_f, open(output_path, 'ab') as dest_f:
        large_dict = pickle.load(src_f)
        for key, value in large_dict.items():
            pickle.dump((key, value), dest_f)
        del large_dict

# 调用示例
merge_large_pickles('dict1.pkl', 'dict2.pkl', 'merged.pkl')

如果后续需要将键值对重新组装为字典,同样可以逐行读取合并后的文件,避免全量加载:

def load_merged_pickle(merged_path):
    merged_dict = {}
    with open(merged_path, 'rb') as f:
        while True:
            try:
                key, value = pickle.load(f)
                merged_dict[key] = value
            except EOFError:
                break
    return merged_dict

方法2:换用更高效的序列化格式

Pickle的内存占用较高,可先将两个字典转换为msgpack(一种轻量高效的序列化格式),再进行合并。msgpack序列化后的文件体积更小,加载时内存占用远低于Pickle。

import pickle
import msgpack

# 将Pickle转存为msgpack
def pickle_to_msgpack(pickle_path, msgpack_path):
    with open(pickle_path, 'rb') as f:
        data = pickle.load(f)
    with open(msgpack_path, 'wb') as f:
        msgpack.dump(data, f)
    del data

# 转换两个文件
pickle_to_msgpack('dict1.pkl', 'dict1.msgpack')
pickle_to_msgpack('dict2.pkl', 'dict2.msgpack')

# 合并msgpack文件
merged_dict = {}
with open('dict1.msgpack', 'rb') as f:
    merged_dict.update(msgpack.load(f))
with open('dict2.msgpack', 'rb') as f:
    merged_dict.update(msgpack.load(f))

# 保存合并结果
with open('merged.msgpack', 'wb') as f:
    msgpack.dump(merged_dict, f)

方法3:用数据库存储,避免全量内存加载

如果不需要一次性获取完整的合并字典,仅需按需查询,可将键值对存入SQLite数据库。这种方式完全不需要将所有数据加载到内存,从根源解决内存溢出问题。

import pickle
import sqlite3

# 初始化数据库
conn = sqlite3.connect('merged_dict.db')
cursor = conn.cursor()
cursor.execute('CREATE TABLE IF NOT EXISTS key_value_store (key TEXT PRIMARY KEY, value BLOB)')

# 写入第一个字典的数据
with open('dict1.pkl', 'rb') as f:
    data = pickle.load(f)
for key, value in data.items():
    cursor.execute('INSERT OR REPLACE INTO key_value_store VALUES (?, ?)', 
                  (key, pickle.dumps(value)))
conn.commit()
del data

# 写入第二个字典的数据
with open('dict2.pkl', 'rb') as f:
    data = pickle.load(f)
for key, value in data.items():
    cursor.execute('INSERT OR REPLACE INTO key_value_store VALUES (?, ?)', 
                  (key, pickle.dumps(value)))
conn.commit()
del data

# 按需查询示例
def get_value(key):
    cursor.execute('SELECT value FROM key_value_store WHERE key = ?', (key,))
    result = cursor.fetchone()
    return pickle.loads(result[0]) if result else None

# 使用示例
print(get_value('204747-44'))
conn.close()

额外注意事项

  • 不要在Jupyter Lab中处理超大对象:Jupyter会保留变量引用,内存回收效率远低于纯Python脚本,建议将代码保存为.py文件直接运行。
  • 运行前关闭其他占用内存的程序,尽可能释放系统可用内存。

内容的提问来源于stack exchange,提问作者Alice Green

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:47:45