mmap.mmap() 返回的是类字节对象,不含 dtype、shape 和 stride 等 NumPy 数组必需的元信息,故不能直接转为数组;必须通过 np.frombuffer()(显式指定 dtype/count)或 np.memmap()(自动管理布局与文件映射)构建合法 NumPy 数组。

不能直接用 mmap 得到 NumPy 数组,必须配合 numpy.frombuffer() 或 numpy.memmap();否则会报 TypeError: buffer is not compatible with array。
为什么 mmap.mmap() 本身不是 NumPy 数组?
mmap.mmap() 返回的是一个类字节对象(memoryview-like),支持切片和字节级读写,但不带 dtype、shape 或 stride 信息。NumPy 数组需要明确的数据类型和内存布局才能安全解释字节流。
- 直接传给
np.array(m)会失败 —— 它尝试拷贝全部内容并推断 dtype,而 mmap 对象不支持__len__()在某些平台(如 Windows)上抛错 -
np.asarray(m)同样失败,原因相同 - 正确路径只有一条:把 mmap 当作 buffer 传给
np.frombuffer(),并显式指定dtype和count
用 np.frombuffer() 创建只读数组(推荐小到中等文件)
适用于已知 dtype 和总元素数的场景,比如 float32 的二进制记录文件。注意:返回的是只读数组,修改会触发 ValueError: assignment destination is read-only。
import numpy as np
import mmap
<p>with open("data.bin", "rb") as f:
mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)</p><h1>假设是 100 万个 float32</h1><pre class='brush:python;toolbar:false;'>arr = np.frombuffer(mm, dtype=np.float32, count=1_000_000)
print(arr.shape) # (1000000,)
# arr[0] = 1.0 ← 这行会报错</pre>-
count必须准确,否则越界读取可能静默截断或引发ValueError - 文件大小必须是
dtype.itemsize * count的整数倍,否则末尾字节被忽略 - 跨平台安全:Linux/macOS/Windows 都适用
用 np.memmap() 创建可读写、带 shape 的数组(推荐大文件或需 reshape 场景)
np.memmap() 是专为内存映射设计的 NumPy 类,底层仍用 mmap,但自动管理 dtype、offset、shape,并支持赋值(需 mode='r+' 或 'c')。
立即学习“Python免费学习笔记(深入)”;
import numpy as np
<h1>创建一个 1000x1000 的 float64 memmap(如果文件不存在则新建)</h1><p>arr = np.memmap("big_matrix.dat", dtype="float64", mode="w+", shape=(1000, 1000))</p><h1>写入数据(实际写入磁盘文件)</h1><p>arr[0, :] = np.arange(1000)
arr.flush() # 强制写回磁盘(非必需,但确保可见)</p><h1>下次打开可读取</h1><p>arr_read = np.memmap("big_matrix.dat", dtype="float64", mode="r", shape=(1000, 1000))
print(arr_read[0, :5]) # [0. 1. 2. 3. 4.]-
mode='r+'表示可读可写,但文件必须已存在且大小匹配;mode='w+'会清空或新建文件 -
shape和dtype一起决定了所需文件大小,不匹配会报ValueError: size of the array must match the size of the file - 修改后不调用
.flush()也可能被写入,但依赖 OS 缓存策略,生产环境建议显式 flush
常见坑与绕过技巧
遇到 OSError: [Errno 22] Invalid argument 或数组全为零,大概率是 mmap 参数或 dtype 不对齐。
- Windows 上
length=0必须配合access=mmap.ACCESS_READ或ACCESS_WRITE,不能用ACCESS_COPY - struct 打包的混合类型(如 int32 + float64)不能直接用
frombuffer()解释,得先用struct.unpack()或np.fromfile()配合dtype描述符 - 想映射超大文件(>2GB)在 32 位 Python 下会失败,确认用的是 64 位解释器
-
np.memmap()的offset参数可用于跳过文件头(如 512 字节 header),但 offset 必须是dtype.itemsize的整数倍,否则报错
真正麻烦的地方不在映射本身,而在 dtype 对齐、文件边界和跨平台 mmap 行为差异 —— 调试时先用 os.path.getsize() 和 dtype.itemsize 手动验算字节数是否匹配。


















