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

Python中不使用Pickle存储大型变量至文件的方法

解决大numpy数组字典存储的MemoryError问题

我完全懂这种处理超大数值数据时卡内存的痛苦!先帮你算笔账:每个(1058694, 10, 9)的numpy数组,如果是float64类型(默认),单个数组就占了1058694*10*9*8 ≈ 750MB,7个加起来就是5GB+。Pickle的问题在于它需要把整个数据集加载到内存再完成序列化,这就难怪会触发MemoryError了。给你几个针对性的解决方案,按推荐程度排序:

1. 用HDF5格式存储(首推)

HDF5是专门为大规模数值数据设计的存储格式,核心优势是支持分块读写——不用把整个数据集塞进内存,而是按需处理小块数据。你可以用h5py库实现,把字典的每个键对应成HDF5文件里的一个数据集:

import h5py
import numpy as np

# 假设你的目标字典是big_dict
big_dict = {
    'feature_set_1': np.random.rand(1058694, 10, 9),
    'feature_set_2': np.random.rand(1058694, 10, 9),
    # ... 剩下5个键值对
}

# 写入HDF5文件,开启分块存储
with h5py.File('large_dataset.h5', 'w') as hdf_file:
    for key, arr in big_dict.items():
        # chunks=True让h5py自动分块,也可以手动指定chunk大小比如(1000,10,9)
        hdf_file.create_dataset(key, data=arr, chunks=True)

# 读取时的灵活操作
with h5py.File('large_dataset.h5', 'r') as hdf_file:
    # 读取完整数组
    full_arr = hdf_file['feature_set_1'][()]
    # 只读取前1000行(无需加载整个数组)
    partial_arr = hdf_file['feature_set_1'][:1000, :, :]

这种方式不仅解决了内存问题,还支持随机访问数据片段,后续做数据分析也更方便。

2. 分文件存储单个numpy数组

如果不想引入HDF5的依赖,也可以把字典里的每个numpy数组单独存成.npy文件,再用一个小型映射文件记录键与文件名的对应关系:

import numpy as np
import pickle
import os

# 创建存储目录
os.makedirs('array_storage', exist_ok=True)

big_dict = {
    'feature_set_1': np.random.rand(1058694, 10, 9),
    # ... 其他键值对
}

# 保存每个数组+记录映射关系
key_filename_map = {}
for idx, (key, arr) in enumerate(big_dict.items()):
    filename = f'array_storage/array_{idx}.npy'
    np.save(filename, arr)
    key_filename_map[key] = filename

# 保存映射字典(这个文件很小,用Pickle完全没问题)
with open('key_mapping.pkl', 'wb') as f:
    pickle.dump(key_filename_map, f)

# 读取数据
with open('key_mapping.pkl', 'rb') as f:
    key_filename_map = pickle.load(f)

loaded_dict = {}
for key, filename in key_filename_map.items():
    loaded_dict[key] = np.load(filename)

这种方案的好处是简单直观,每个数组独立存储,内存只需要处理单个数组的大小,完全不会触发MemoryError。

3. 优化Pickle的序列化方式(不推荐)

如果非要用Pickle,只能尝试拆分序列化流程,但本质上还是要加载单个数组到内存,只能缓解不能彻底解决问题:

import pickle
import numpy as np

big_dict = {
    'feature_set_1': np.random.rand(1058694, 10, 9),
    # ... 其他键值对
}

# 拆分写入:先存键,再逐个存数组
with open('big_data.pkl', 'wb') as f:
    pickle.dump(list(big_dict.keys()), f)
    for arr in big_dict.values():
        pickle.dump(arr, f)

# 读取时对应还原
with open('big_data.pkl', 'rb') as f:
    keys = pickle.load(f)
    loaded_dict = {}
    for key in keys:
        loaded_dict[key] = pickle.load(f)

这种方法只是避免了一次性把所有数组塞进内存,但单个数组的内存占用还是存在,所以只适合内存刚好差一点的情况,远不如前两种方案靠谱。


内容的提问来源于stack exchange,提问作者Gian Mauro Musso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:14:22