← 返回题目列表

Python mmap 有什么用?什么时候适合使用内存映射文件?

高频 困难 第 15 / 27 题 更新于 2026/07/31
mmap内存映射大文件随机访问

简化版

mmap 可以把文件映射到进程虚拟内存,让程序像访问 bytes/bytearray 一样访问文件内容。它适合大文件随机访问、搜索、局部修改和进程间共享内存,但不等于把大文件免费读入内存,也要注意关闭、刷新和平台差异。

详细版

普通 read() 会把文件内容读到 Python 对象里;mmap 创建的是文件到虚拟内存的映射,操作系统按需把页面调入内存。对超大文件,如果只访问少量片段,mmap 可能更高效。

import mmap

with open("data.bin", "r+b") as f:
    with mmap.mmap(f.fileno(), 0) as mm:
        pos = mm.find(b"ERROR")
        if pos != -1:
            print(pos)

它不是所有大文件场景的银弹。顺序读取大文件时,普通迭代或分块 read 已经很好;mmap 更适合随机访问和搜索。

完整版教学

一、mmap 解决什么问题

大文件处理有两类需求:顺序扫描和随机访问。顺序扫描用 for line in fread(chunk) 就很好;随机访问大量位置时,频繁 seek/read 代码复杂,mmap 可以把文件当作连续内存来用。

普通 I/O:
seek -> read -> seek -> read

mmap:
mm[pos:pos+100]

假设文件 10GB,但只查找某个关键字或访问几个偏移片段,mmap 不需要构造一个 10GB 的 Python bytes。

二、mmap 不是把文件全读进内存

内存映射使用虚拟内存。映射 10GB 文件并不意味着立刻占用 10GB 物理内存。操作系统会按页面把访问到的部分调入内存。

虚拟地址空间: 映射 10GB
物理内存: 按需加载被访问页面

但这也不意味着没有成本。如果你最终顺序访问整个 10GB,操作系统仍然要把页面读进来;只是路径不同。

三、读写模式怎么选

打开文件模式和 mmap access 参数决定能否修改。只读搜索用只读模式;需要修改文件内容,要用可写映射,并在必要时 flush。

with open("data.bin", "r+b") as f:
    with mmap.mmap(f.fileno(), 0) as mm:
        mm[0:4] = b"ABCD"
        mm.flush()
模式用途
只读映射搜索、解析
写映射局部修改文件
copy-on-write修改不写回原文件

写入时不能随便改变文件大小。mmap 适合覆盖已有区域,不适合频繁追加变长内容。

四、搜索为什么方便

mmap 对象支持类似 bytes 的操作,比如切片、find。搜索日志或二进制文件中特定标记时很方便。

pos = mm.find(b"\x50\x4b\x03\x04")

如果文件很大,mm.find() 底层仍要扫描,但不需要手写分块边界处理。普通分块搜索还要处理关键字跨 chunk 的情况,mmap 可以减少这类复杂度。

mmap 的甜点区是“大文件 + 随机访问/搜索/局部修改”,不是替代所有文件读取。

五、生命周期和资源释放

mmap 对象和文件描述符都要关闭。推荐用双层 with,确保异常时也释放资源。Windows 上如果 mmap 没关闭,可能导致文件无法删除或修改。

with open(path, "rb") as f:
    with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mm:
        ...

写映射时要理解 flush 语义。flush() 请求把修改刷回文件,但真正落盘还涉及操作系统缓存和文件系统行为;强一致落盘还要结合 fsync 等。

六、和普通分块读取怎么选

如果只是逐行处理日志,普通文件迭代更简单。如果要按偏移跳转、查找二进制签名、随机读取索引区域,mmap 更自然。

场景推荐
逐行读文本日志文件迭代
大文件固定偏移读取mmap
搜索二进制标记mmap
流式上传下载分块 read/write
频繁追加写普通文件/日志系统

选择标准是访问模式,而不是文件大小本身。

七、常见误区与追问

  • 误区:mmap 会立刻把整个文件读入内存。 它建立虚拟内存映射,页面按需加载。
  • 误区:大文件都应该用 mmap。 顺序读取用普通分块更简单可靠。
  • 误区:mmap 可以随意扩展文件。 它更适合映射已有大小区域,变长追加不方便。
  • 追问:mmap 修改后要不要 flush? 需要考虑 flush,重要数据还要考虑 fsync。
  • 追问:Windows 上 mmap 有什么坑? 未关闭映射时文件可能无法删除或改名。
  • 追问:mmap 和 shared_memory 有什么区别? mmap 可映射文件,也可用于共享;shared_memory 更偏进程间共享内存块。
  • 追问:搜索跨 chunk 问题 mmap 怎么处理? mmap 视图连续,不需要手写 chunk 边界拼接。

八、加强记忆

mmap 记成“把文件映射成可切片的内存视图”。它适合大文件随机访问、搜索和局部覆盖,不是免费把所有 I/O 变快。顺序读用分块,随机读用 mmap;写入要 flush,使用后要 close。