Python中的内存映射(Memory Mapping)与mmap模块详解
字数 375 2025-11-12 09:57:01
Python中的内存映射(Memory Mapping)与mmap模块详解
一、内存映射的基本概念
内存映射是一种将文件或设备直接映射到进程虚拟内存空间的技术。映射后,文件内容可以直接通过内存地址访问,就像访问普通内存一样。
三、mmap模块基础使用
import mmap
# 创建测试文件
with open('test.dat', 'wb') as f:
f.write(b'Hello, Memory Mapping!')
# 基本内存映射操作
with open('test.dat', 'r+b') as f:
# 创建内存映射对象
with mmap.mmap(f.fileno(), 0) as mm:
# 读取内容
print(mm.read()) # b'Hello, Memory Mapping!'
# 修改内容
mm.seek(0)
mm.write(b'Modified Content!')
四、mmap参数详解
import mmap
# 1. length参数:指定映射区域大小
with open('data.bin', 'w+b') as f:
f.write(b'X' * 100) # 准备100字节文件
# 映射整个文件
mm = mmap.mmap(f.fileno(), 0) # length=0表示映射整个文件
# 映射部分文件(前50字节)
mm_partial = mmap.mmap(f.fileno(), 50)
# 2. access参数:访问权限控制
with open('data.bin', 'r+b') as f:
# 不同访问模式
mm_readonly = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
mm_write = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_WRITE)
mm_copy = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_COPY)
五、内存映射的寻址操作
import mmap
with open('data.bin', 'w+b') as f:
f.write(b'Python Memory Mapping Example')
f.flush()
with mmap.mmap(f.fileno(), 0) as mm:
# 类似文件操作的寻址
print("当前位置:", mm.tell()) # 0
# 移动指针并读取
mm.seek(7) # 移动到第7个字节
print("从位置7读取:", mm.read(6)) # b'Memory'
# 直接索引访问(类似列表)
print("索引访问:", mm[0:6]) # b'Python'
# 切片修改
mm[0:6] = b'PYTHON'
print("修改后:", mm[:])
六、内存映射的高级特性
import mmap
import os
# 1. 匿名映射(不关联文件)
def anonymous_mapping_example():
# 创建匿名映射区域(Linux/Unix系统)
size = 1024 # 1KB
if hasattr(mmap, 'MAP_ANONYMOUS'):
mm = mmap.mmap(-1, size, flags=mmap.MAP_ANONYMOUS)
mm.write(b'Anonymous Mapping Data')
mm.seek(0)
print("匿名映射内容:", mm.read())
mm.close()
# 2. 大文件处理示例
def large_file_processing():
# 创建大测试文件
with open('large.dat', 'w+b') as f:
# 写入1MB数据
data = b'A' * 1024 * 1024
f.write(data)
f.flush()
# 分块处理大文件
chunk_size = 64 * 1024 # 64KB块大小
file_size = os.path.getsize('large.dat')
for offset in range(0, file_size, chunk_size):
# 映射文件的不同部分
with mmap.mmap(f.fileno(),
length=min(chunk_size, file_size - offset),
offset=offset) as mm:
# 处理当前块
processed_data = mm.read().replace(b'A', b'B')
mm.seek(0)
mm.write(processed_data)
# 3. 进程间通信示例
def ipc_with_mmap():
import multiprocessing
def worker(shared_mem):
# 子进程修改共享内存
shared_mem.seek(0)
shared_mem.write(b'Modified by child process')
# 创建共享内存文件
with open('shared.dat', 'w+b') as f:
f.write(b'Initial data')
f.flush()
# 父进程创建映射
with mmap.mmap(f.fileno(), 0) as shared_mem:
# 创建子进程
p = multiprocessing.Process(target=worker, args=(shared_mem,))
p.start()
p.join()
# 读取修改后的内容
shared_mem.seek(0)
print("共享内存内容:", shared_mem.read())
七、性能优化实践
import mmap
import time
def performance_comparison():
file_size = 100 * 1024 * 1024 # 100MB
# 准备测试文件
with open('perf_test.dat', 'w+b') as f:
f.write(b'0' * file_size)
# 传统文件IO
start_time = time.time()
with open('perf_test.dat', 'r+b') as f:
for i in range(0, file_size, 4096):
f.seek(i)
data = f.read(4096)
f.seek(i)
f.write(b'1' * len(data))
traditional_time = time.time() - start_time
# 内存映射IO
start_time = time.time()
with open('perf_test.dat', 'r+b') as f:
with mmap.mmap(f.fileno(), 0) as mm:
for i in range(0, file_size, 4096):
mm[i:i+4096] = b'2' * 4096
mmap_time = time.time() - start_time
print(f"传统IO时间: {traditional_time:.2f}s")
print(f"内存映射时间: {mmap_time:.2f}s")
print(f"性能提升: {traditional_time/mmap_time:.1f}x")
八、实际应用场景
- 大文件处理:避免将整个文件加载到内存
- 进程间通信:多个进程共享同一内存区域
- 数据库系统:实现高效的缓存机制
- 实时数据处理:低延迟的数据访问
九、注意事项
- 文件大小变化时需要重新映射
- 确保有足够的虚拟内存空间
- 注意同步问题(多进程/多线程环境)
- 及时调用flush()确保数据持久化
内存映射通过减少数据拷贝次数,在特定场景下可显著提升IO性能,是高性能Python应用的重要技术。