Python大型布尔嵌套列表变量的高效存储与加载方案咨询
大型变量存储与加载的高效解决方案
先优化v3的内存占用
你定义的v3 = [[[False] for x in range(6000)] for x in range(6000)]是嵌套列表结构,每个布尔值都是Python对象,内存占用极高(单个Python bool对象约28字节,6000*6000个元素要占约6GB)。首先把它转换成numpy布尔数组,numpy的bool_类型仅占1字节/元素,内存直接降到34MB左右:
import numpy as np # 直接初始化numpy布尔数组(比转嵌套列表更高效) v3 = np.zeros((6000, 6000), dtype=np.bool_) # 修改值时直接用索引,比如v3[100][200] = True
推荐的存储/加载方案
方案1:numpy savez_compressed(最适合混合numpy+Python对象)
numpy的savez_compressed可以打包多个变量,自动压缩,速度快且兼容性好:
# 保存 np.savez_compressed('large_data.npz', v1=v1, v2=v2, v3=v3) # 加载 loaded_data = np.load('large_data.npz') v1_loaded = loaded_data['v1'] v2_loaded = loaded_data['v2'] v3_loaded = loaded_data['v3'] # 若需要转回嵌套列表(不推荐,除非业务必须) v3_list = v3_loaded.tolist()
方案2:h5py(适合超大型数据,支持部分加载)
如果数据量持续增长,h5py支持分块存储和按需加载单个变量,避免一次性占用大量内存:
import h5py # 保存 with h5py.File('large_data.h5', 'w') as f: f.create_dataset('v1', data=v1) f.create_dataset('v2', data=v2) f.create_dataset('v3', data=v3, dtype='bool') # 加载 with h5py.File('large_data.h5', 'r') as f: v1_loaded = f['v1'][()] # 加[()]读取整个数组 v2_loaded = f['v2'][()] v3_loaded = f['v3'][()]
方案3:cloudpickle(修复标准pickle的兼容性问题)
你遇到的FrozenNDArray报错是因为标准pickle对pandas内部对象的序列化兼容性差,换用cloudpickle可以兼容复杂的Python/pandas对象:
import cloudpickle # 保存 with open('large_data.pkl', 'wb') as f: cloudpickle.dump([v1, v2, v3], f) # 加载 with open('large_data.pkl', 'rb') as f: v1_loaded, v2_loaded, v3_loaded = cloudpickle.load(f)
方案4:稀疏矩阵(当v3中True数量极少时)
如果v3里大部分是False,用scipy稀疏矩阵存储,存储大小只和True的数量正相关:
from scipy.sparse import coo_matrix # 转稀疏矩阵 v3_sparse = coo_matrix(v3) # 保存 with open('v3_sparse.pkl', 'wb') as f: cloudpickle.dump(v3_sparse, f) # 加载转回稠密数组 with open('v3_sparse.pkl', 'rb') as f: v3_sparse_loaded = cloudpickle.load(f) v3_loaded = v3_sparse_loaded.todense()
关于pd.read_pickle的问题
pd.read_pickle是为pandas对象设计的,它会自动解析非pandas结构,导致你的布尔嵌套列表被转换成统计值,因此不适合用来存储混合类型的大型变量。
内容的提问来源于stack exchange,提问作者Anas.S
相关产品推荐
相关产品推荐

