mmap读二进制文件最省内存,适合大文件随机访问;必须用mmap的场景是文件远超内存或需频繁跳转读取;关键参数length=0映射全文件(Windows需显式指定大小),access默认READ最安全,offset须页对齐。

直接用 mmap 读二进制文件最省内存,尤其适合大文件随机访问——它不把整个文件加载进 Python 对象,而是让操作系统帮你映射到进程地址空间。
什么时候必须用 mmap 而不是 open().read()?
当文件远大于可用内存(比如几个 GB 的日志、数据库快照、视频帧数据),或你需要频繁跳转读取不同偏移位置(如解析自定义二进制协议头、查找特定 magic bytes),mmap 就不是“可选”,而是刚需。普通 read() 会触发完整拷贝和内存分配,而 mmap 只在实际访问页时由 OS 按需加载。
- 典型场景:
ELF文件解析、内存数据库快照读取、传感器原始 bin 数据切片 - 反例:读取几十 KB 的配置二进制块,用
mmap反而多一层系统调用开销 - 注意:
mmap映射的是字节序列,Python 中表现为memoryview或bytes类型,没有自动解码
mmap.mmap() 的关键参数怎么选?
最易错的是 length 和 access。传错会导致 ValueError 或静默截断:
-
length=0表示映射整个文件(推荐用于只读场景),但 Windows 下必须显式传os.path.getsize(fp) -
access=mmap.ACCESS_READ是默认且最安全的;若要写入,必须用ACCESS_WRITE,且文件需以'r+b'打开 -
offset必须是页对齐的(通常 4096 字节),否则抛OSError: Invalid argument - Linux/macOS 支持
ACCESS_COPY(写时复制),但 Python 文档明确说“不保证跨平台”,别依赖
如何安全地读取结构化二进制字段?
别直接对 mmap 对象做 struct.unpack() —— 它可能跨页边界,而 mmap 对象不支持 slice 的 memoryview 语义。正确做法是先切片再转换:
立即学习“Python免费学习笔记(深入)”;
import mmap
import struct
<p>with open('data.bin', 'rb') as f:
with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mm:</p><h1>读前 4 字节作为 uint32</h1><pre class='brush:python;toolbar:false;'> header_bytes = mm[:4] # ✅ 返回 bytes,可直接 unpack
version = struct.unpack('<I', header_bytes)[0]
# 读偏移 1024 开始的 8 字节 double
payload = mm[1024:1032] # ✅ 切片后是 bytes
value = struct.unpack('<d', payload)[0]</pre>- 切片操作(
mm[a:b])返回bytes,不是新 mmap;这是安全的 - 避免
mm.read(4)—— 它会移动内部游标,且在只读 mmap 上可能抛异常 - 如果字段位置动态计算,务必检查
a < len(mm),否则切片越界返回空 bytes,struct.unpack会报struct.error: unpack requires a buffer of 4 bytes
真正麻烦的是跨平台页对齐和 Windows 下的 length 处理——很多脚本在 Linux 跑得好好的,一到 Windows 就卡在 mmap 初始化失败,根源往往就在这两个参数没兜住。


















