ZipFile打开的文件无法使用mmap,报UnsupportedOperation: fileno错误求解决
压缩包内大文件高效搜索方案:替代mmap的解决办法
问题根源
zipfile.ZipFile.open()返回的是ZipExtFile流对象,它并非真实的磁盘文件,没有对应的系统文件描述符(fileno()),而mmap依赖系统级文件句柄才能工作,这就是你遇到UnsupportedOperation: fileno错误的原因。
解决方案
根据文件大小和内存情况,可选择以下两种高效方案:
方案1:内存映射缓冲区(适合中等大小文件)
把压缩包内文件的内容读取到内存,再创建匿名内存映射来模拟mmap的使用,无需磁盘IO:
import zipfile import mmap import io with zipfile.ZipFile(r"path\test.zip", "r") as zip_ref: with zip_ref.open("myfile", 'rb') as zip_file: # 读取文件内容到内存 file_content = zip_file.read() # 创建匿名内存映射,大小与文件内容一致 with mmap.mmap(-1, len(file_content), access=mmap.ACCESS_READ) as mem_map: # 将内容写入映射区域 mem_map.write(file_content) # 后续可像操作普通mmap一样执行搜索 mem_map.seek(0) if mem_map.find(b"要搜索的字符串") != -1: print("找到目标内容")
方案2:临时文件中转(适合超大文件)
如果文件大小超过内存容量,可将压缩包内文件写入临时磁盘文件,再对临时文件使用mmap,用完自动清理:
import zipfile import mmap import tempfile import os with zipfile.ZipFile(r"path\test.zip", "r") as zip_ref: # 创建临时文件(关闭后不自动删除,后续手动清理) with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_path = temp_file.name try: # 将压缩包内文件写入临时文件 with zip_ref.open("myfile", 'rb') as zip_file, open(temp_path, 'wb') as f: f.write(zip_file.read()) # 对临时文件使用mmap with open(temp_path, 'rb') as f: with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mem_map: # 执行搜索操作 if mem_map.find(b"要搜索的字符串") != -1: print("找到目标内容") finally: # 确保临时文件被删除 os.unlink(temp_path)
补充说明
- 方案1的优势是速度快,无磁盘开销,但受限于内存大小;
- 方案2适合处理GB级别的超大文件,仅需少量内存,但会产生临时磁盘IO;
- 两种方案都能保留mmap高效的字符串搜索特性,满足批量处理压缩包内大文本文件的需求。
内容的提问来源于stack exchange,提问作者Jon1
相关产品推荐
相关产品推荐

