使用numpy.load()加载70GB数据时遭遇EOFError问题求助
解决Python2.7下numpy.load超大npy文件的EOFError问题
首先,EOFError本质是读取文件时意外遇到了文件末尾,结合你70GB超大文件的场景,大概率是以下几个原因导致的,我给你逐一分析并给出解决方案:
1. 先确认文件本身是否完整
70GB的文件在保存过程中很容易因为各种意外中断(比如磁盘空间不足、进程被意外终止、存储设备故障等)导致文件不完整。你可以先做两个检查:
- 对比文件实际大小和理论计算值:假设你的数据是
float16类型(因为(40030025625619)*2字节 ≈ 69.5GB,刚好和你说的70GB匹配),计算出来的理论大小应该和文件实际大小基本一致(误差在几MB内都正常)。如果实际大小差很多,说明保存时出了问题,必须重新保存,保存时确保:- 磁盘剩余空间至少是文件大小的1.5倍以上
- 保存过程中不要中断进程,避免机器休眠或断电
- 尝试用
numpy.load的mmap_mode先只读映射文件,看看能不能读取部分数据:my_data = np.load('my_data.npy', mmap_mode='r') print(my_data.shape) # 先确认形状是否正确
如果连形状都读不出来,那基本可以确定文件损坏了。
2. 内存不足导致读取中断
加载70GB的数组到内存需要至少80GB以上的可用内存(numpy处理数组时还要额外的内存开销),如果你的机器内存不够,系统会强制终止读取进程,进而触发EOFError。这种情况下,推荐两种处理方式:
- 内存映射加载:使用
mmap_mode='r'(只读)或mmap_mode='r+'(可读可写)加载文件,这样numpy不会把整个数组加载到内存,而是按需从磁盘读取,几乎不占用内存:my_data = np.load('my_data.npy', mmap_mode='r') # 后续处理时可以像正常数组一样切片访问,比如取第一个样本 sample = my_data[0, ...] - 分块保存与加载:如果内存映射还是有问题,建议重新保存时把大数组拆分成多个小块,比如按第一个维度拆分:
加载时再逐个读取:# 重新保存的代码 dataset = np.asarray(dataset) # 拆成4个100长度的块 for i in range(4): block = dataset[i*100 : (i+1)*100, ...] np.save(f'my_data_block_{i}.npy', block)# 加载分块数据 blocks = [] for i in range(4): block = np.load(f'my_data_block_{i}.npy') blocks.append(block) my_data = np.concatenate(blocks, axis=0)
这样每个块只有17.5GB左右,内存压力会小很多。
3. Python2.7和numpy版本的局限性
Python2.7已经停止维护很久了,旧版本的numpy在处理超大数组时可能存在bug。你可以尝试升级到Python2.7支持的最后一个numpy版本(1.16.6),看看能否解决问题:
pip install numpy==1.16.6 --user
如果升级后还是不行,建议尽量迁移到Python3环境(比如Python3.8+),新版本的numpy对大文件支持更好,也更稳定。
4. 检查文件系统限制
虽然现在大部分文件系统(比如ext4、NTFS)都支持超大文件,但也不排除某些特殊场景下的限制,比如网络存储的单个文件大小上限。你可以确认一下存储该文件的文件系统是否支持100GB以上的单个文件。
内容的提问来源于stack exchange,提问作者eric lardon
相关产品推荐
相关产品推荐

