如何向Numpy的.npz文件写入数据而不覆盖原有内容?
这个问题我之前也碰到过!numpy的savez()确实没有直接追加变量的功能,因为它生成的.npz文件本质是一个ZIP压缩包,每次调用都会重新创建整个压缩包,自然会覆盖原有内容。不过有两种靠谱的解决方案,你可以根据自己的场景选择:
方法1:加载现有变量后合并保存
这种方法适合文件不大、变量数量不多的情况,思路很简单:先把文件里已有的所有变量读出来,和新变量合并成一个字典,再重新保存整个字典。
示例代码:
import numpy as np # 第一次保存变量a a = np.array([1, 2, 3]) np.savez('file.npz', a=a) # 要追加变量b时,先加载已有数据 existing_data = np.load('file.npz') # 把加载的对象转成普通字典,方便添加新变量 merged_data = dict(existing_data) # 添加新变量b b = np.array([4, 5, 6]) merged_data['b'] = b # 重新保存所有变量 np.savez('file.npz', **merged_data) # 验证结果 loaded = np.load('file.npz') print(loaded.keys()) # 输出: ['a', 'b']
注意:如果你的.npz文件很大,加载所有变量会占用较多内存,这时候更推荐下面的方法。
方法2:直接操作ZIP文件追加(适合大文件)
因为.npz本质是ZIP包,里面每个变量对应一个.npy文件,我们可以用Python内置的zipfile模块直接往ZIP包里追加新的.npy文件,不需要加载所有现有变量。
示例代码:
import numpy as np import zipfile import io def append_to_npz(file_path, **kwargs): # 先检查要追加的变量名是否已存在 existing_keys = [] with zipfile.ZipFile(file_path, 'r') as zf: # 提取所有.npy文件名,去掉后缀得到变量名 existing_keys = [name[:-4] for name in zf.namelist() if name.endswith('.npy')] duplicate_keys = [key for key in kwargs if key in existing_keys] if duplicate_keys: raise ValueError(f"变量名 {duplicate_keys} 已存在于文件中,请更换名称或处理重复") # 以追加模式打开ZIP文件,写入新变量 with zipfile.ZipFile(file_path, 'a', zipfile.ZIP_DEFLATED) as zf: for key, arr in kwargs.items(): # 将数组保存到内存缓冲区 buffer = io.BytesIO() np.save(buffer, arr) buffer.seek(0) # 写入ZIP包,文件名格式为「变量名.npy」 zf.writestr(f"{key}.npy", buffer.getvalue()) # 第一次保存变量a a = np.array([1, 2, 3]) np.savez('file.npz', a=a) # 追加变量b b = np.array([4, 5, 6]) append_to_npz('file.npz', b=b) # 再追加变量c c = np.array([7, 8, 9]) append_to_npz('file.npz', c=c) # 验证结果 loaded = np.load('file.npz') print(loaded.keys()) # 输出: ['a', 'b', 'c']
这个方法的优势是不需要加载整个文件,内存占用小,适合处理大数组或大量变量的场景。
内容的提问来源于stack exchange,提问作者user8930103
相关产品推荐
相关产品推荐

