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")

八、实际应用场景

  1. 大文件处理:避免将整个文件加载到内存
  2. 进程间通信:多个进程共享同一内存区域
  3. 数据库系统:实现高效的缓存机制
  4. 实时数据处理:低延迟的数据访问

九、注意事项

  1. 文件大小变化时需要重新映射
  2. 确保有足够的虚拟内存空间
  3. 注意同步问题(多进程/多线程环境)
  4. 及时调用flush()确保数据持久化

内存映射通过减少数据拷贝次数,在特定场景下可显著提升IO性能,是高性能Python应用的重要技术。

Python中的内存映射(Memory Mapping)与mmap模块详解 一、内存映射的基本概念 内存映射是一种将文件或设备直接映射到进程虚拟内存空间的技术。映射后,文件内容可以直接通过内存地址访问,就像访问普通内存一样。 三、mmap模块基础使用 四、mmap参数详解 五、内存映射的寻址操作 六、内存映射的高级特性 七、性能优化实践 八、实际应用场景 大文件处理 :避免将整个文件加载到内存 进程间通信 :多个进程共享同一内存区域 数据库系统 :实现高效的缓存机制 实时数据处理 :低延迟的数据访问 九、注意事项 文件大小变化时需要重新映射 确保有足够的虚拟内存空间 注意同步问题(多进程/多线程环境) 及时调用flush()确保数据持久化 内存映射通过减少数据拷贝次数,在特定场景下可显著提升IO性能,是高性能Python应用的重要技术。