原文链接:http://www.juzicode.com/python-module-memoryview
Python的memoryview
模块提供了一种零拷贝方式访问二进制数据缓冲区的接口,是处理大型数据集和优化内存性能的核心工具。它允许直接操作底层内存而无需数据复制,特别适用于科学计算、音视频处理和网络通信等场景。
应用场景
- 大型二进制数据的高效处理
- 图像/视频帧的零拷贝操作
- 网络协议数据的直接解析
- 加密算法的字节级操作
- 实时音视频流处理
安装与导入
memoryview
是Python内置模块,无需额外安装:
# 直接导入使用
data = bytearray(b'juzicode.com')
mv = memoryview(data)
使用方法
1)读取内存
创建memoryveiw对象与读取数据
# juzicode.com/VX公众号:juzicode
# 创建一个 bytes 对象
data = b"Hello, juzicode!"
# 创建 memoryview 对象
mv = memoryview(data)
# 访问 memoryview 中的数据
print(mv[0])
print(mv[:15].tobytes())
运行结果:
72
b'Hello, juzicode'
2)修改数据
创建内存视图并修改底层数据:
# juzicode.com/VX公众号:juzicode
# 创建字节数组
data = bytearray(b'juzicode.com')
print("原始数据:", data)
# 创建内存视图
mv = memoryview(data)
# 修改第一个字节
mv[0] = ord('J')
print("修改后数据:", data)
运行结果:
原始数据: bytearray(b'juzicode.com')
修改后数据: bytearray(b'Juzicode.com')
3)切片操作优化
零拷贝切片处理大型文件,内存视图切片不复制数据:
# juzicode.com/VX公众号:juzicode
# 创建1MB数据
large_data = bytearray(1024*1024)
# 传统切片(产生数据拷贝)
slice1 = large_data[1000:2000]
# 内存视图切片(零拷贝)
mv = memoryview(large_data)
slice2 = mv[1000:2000]
# 验证内存地址
print("切片内存地址:", id(slice1))
print("视图切片地址:", id(slice2))
print("底层数据地址:", id(large_data))
print(type(slice2))
print(type(slice1))
运行结果:
底层数据地址: 2037264380528
切片内存地址: 2037264377968
视图切片地址: 2037263930304
<class 'memoryview'>
<class 'bytearray'>
4)协议解析优化
高效解析网络数据包:
# juzicode.com/VX公众号:juzicode
def parse_packet(packet):
"""使用memoryview解析网络数据包"""
mv = memoryview(packet)
# 解析头部字段(零拷贝)
version = mv[0] >> 4
header_len = (mv[0] & 0x0F) * 4
src_ip = bytes(mv[12:16])
# 返回切片视图(不复制数据)
return {
'version': version,
'header_len': header_len,
'payload': mv[header_len:]
}
# 模拟IP数据包
ip_packet = bytearray(b'\x45\x00\x00\x1c\x00\x00\x00\x00\x40\x11\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01Hello!')
result = parse_packet(ip_packet)
print("解析结果:", result)
print("Payload:", bytes(result['payload']))
运行结果:
解析结果: {'version': 4, 'header_len': 20, 'payload': <memory at 0x000001DA55F28AC0>}
Payload: b'Hello!'
5)数据加密
展示加密/解密过程及性能优势
# juzicode.com/VX公众号:juzicode
def xor_encrypt(data, key):
"""使用内存视图进行高效异或加密"""
mv = memoryview(data)
key_len = len(key)
with mv as m:
# 逐字节进行异或加密
for i in range(len(m)):
m[i] ^= key[i % key_len]
return data
# 测试加密/解密
original = bytearray(b"Secret data for juzicode.com")
key = b"juzi"
print("原始数据:", original)
# 加密
encrypted = xor_encrypt(original.copy(), key)
print("加密数据:", encrypted)
# 解密
decrypted = xor_encrypt(encrypted.copy(), key)
print("解密数据:", decrypted)
# 性能对比
large_data = bytearray(100 * 1024 * 1024) # 100MB数据
# 普通方法
def xor_slow(data, key):
return bytearray(b ^ key[i % len(key)] for i, b in enumerate(data))
# 内存视图方法
print("\n性能测试 (100MB数据):")
%timeit xor_encrypt(large_data.copy(), key) # 内存视图
%timeit xor_slow(large_data.copy(), key) # 传统方法
运行结果:
原始数据: bytearray(b'Secret data for juzicode.com')
加密数据: bytearray(b'9\x10\x19\x1b\x0f\x01Z\r\x0b\x01\x1bI\x0c\x1a\x08I\x00\x00\x00\x00\t\x1a\x1e\x0cD\x16\x15\x04')
解密数据: bytearray(b'Secret data for juzicode.com')
总结
memoryview核心优势:
- 零拷贝操作提升大数据处理性能
- 原生支持缓冲区协议标准
- 兼容bytes/bytearray/array.array等类型
注意事项:
- 原始数据被修改时会同步影响视图
- 不支持所有Python序列操作
- 释放原始对象后视图将失效