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

Numpy memmap加载.npy文件数组损坏,如何正确使用?

正确使用numpy.memmap加载npy文件的方法

问题根源

直接用np.memmap加载.npy文件会出错,因为.npy文件并非纯二进制数据——文件开头包含元信息头部(存储了数组的 dtype、shape、版本等数据),直接memmap会把头部字节当成数组数据的一部分,导致形状混乱、数据损坏。

解决方法:跳过npy文件头部加载

要正确memmap .npy 文件,需要先计算头部的总长度,然后从头部结束的位置开始映射数据。

步骤1:获取npy文件的头部偏移量

以下函数可以读取npy文件的头部信息,计算出数据起始的字节偏移:

import numpy as np

def get_npy_data_offset(file_path):
    with open(file_path, 'rb') as f:
        # 验证npy文件魔法数
        magic = f.read(6)
        if magic != b'\x93NUMPY':
            raise ValueError("输入不是有效的npy文件")
        
        # 读取版本号
        version_major, version_minor = np.frombuffer(f.read(2), dtype=np.uint8)
        
        # 读取头部长度
        if version_major == 1:
            header_len = np.frombuffer(f.read(2), dtype=np.uint16)[0]
        elif version_major == 2:
            header_len = np.frombuffer(f.read(4), dtype=np.uint32)[0]
        else:
            raise ValueError(f"不支持的npy版本:{version_major}.{version_minor}")
        
        # 计算头部总长度(含魔法数、版本、长度标识、头部内容)
        base_header_len = 6 + 2 + (2 if version_major ==1 else 4) + header_len
        # numpy的npy文件数据部分按64字节对齐,需调整偏移量
        alignment = 64
        return ((base_header_len + alignment -1) // alignment) * alignment

步骤2:加载memmap数组

先获取偏移量,再结合已知的数组shape和dtype(可通过np.load小范围读取或提前记录),创建正确的memmap对象:

# 示例操作
offset = get_npy_data_offset('f.npy')
# 若已知shape和dtype可直接指定,否则先读取元信息(避免加载整个数组)
temp = np.load('f.npy', mmap_mode='r')  # 临时加载仅读取头部,不占用大量内存
target_shape = temp.shape
target_dtype = temp.dtype

# 创建正确的memmap
c = np.memmap('f.npy', dtype=target_dtype, mode='r', shape=target_shape, offset=offset)

# 验证结果
assert np.array_equal(c, temp)

替代方案:保存为纯二进制文件

如果可以重新保存数据,可直接将数组保存为无头部的纯二进制文件,这样memmap时无需处理偏移:

# 保存纯二进制
a = np.arange(65536)
a.tofile('f.bin')

# 直接memmap加载
c = np.memmap('f.bin', dtype=np.int64, mode='r', shape=a.shape)

注意:此方法需要自行记录数组的dtype和shape,否则无法正确加载。

针对真实数据的pickle问题说明

你的真实数据无法用np.load(mmap_mode='r')加载,是因为文件包含pickle序列化的内容,但np.memmap本身不处理pickle——只要你能提前获取到数组的shape和dtype(比如从数据文档、元数据文件,或用np.load读取头部而不加载整个数组),上述跳过头部的memmap方法依然有效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:09:53