Python以rb模式读取正在变更的大文件问题及可靠读取方案咨询
读取过程中文件被修改的影响与解决方案
读取时文件变更引发的常见问题
- 内容不一致:读取过程中其他进程修改文件内容,你最终拿到的会是修改前+修改后的混合数据,既不是读取启动时的完整版本,也不是修改完成后的完整版本,属于完全不可用的脏数据。
- 长度异常:如果其他进程截断文件,你会提前遇到EOF,读取到比实际原长度更短的内容;如果其他进程追加内容,而你已经读到过原文件末尾,最终拿到的内容会缺失后续新增的部分。
- 结构化文件损坏:如果你读取的是压缩包、图片、数据库文件等有固定格式的二进制文件,混合了修改后的内容会直接破坏文件结构,后续无法正常解析使用。
大文件场景下的可靠读取方案
你原本的全量读入内存的方案只适合小文件,大文件场景可以用以下几种方案,都不需要占用大量内存:
方案1:硬链接快照(跨平台通用,同分区下零额外磁盘开销)
硬链接是文件系统级的特性,给目标文件创建硬链接后,原文件被修改、删除都不会影响硬链接指向的原始文件内容,也不会额外占用磁盘空间。
操作步骤:
- 读取前调用
os.link(源文件路径, 临时硬链接路径)创建硬链接 - 从临时硬链接路径分块读取内容,直接写入你需要的临时文件或者BytesIO对象,块大小建议设置为1MB~4MB,平衡读取效率和内存占用
- 读取完成后删除临时硬链接即可
注意:硬链接只能在同一个磁盘分区内创建,如果你的临时目录和源文件不在同一个分区,该方案不适用。
方案2:文件系统快照(适合Unix/Linux/macOS平台)
如果你的文件存放在支持快照的文件系统(ext4、btrfs、ZFS、APFS等)上,可以在读取前先创建卷的只读快照,直接从快照中读取文件,读取完成后删除快照即可。该方案可以同时处理批量大文件的一致性读取需求,全程不会受原文件修改影响。
方案3:分块读取+哈希校验(适合可以拿到源文件预期哈希值的场景)
如果你可以提前获取到源文件的正确SHA256/MD5哈希值,可以边分块读取边做哈希校验,确认读取到的内容完整正确:
import hashlib from io import BytesIO def read_large_file(src_path: str, chunk_size: int = 1024*1024, expected_sha256: str = None) -> BytesIO: dst_stream = BytesIO() hash_obj = hashlib.sha256() with open(src_path, 'rb') as f: while chunk := f.read(chunk_size): dst_stream.write(chunk) hash_obj.update(chunk) # 校验内容完整性 if expected_sha256 and hash_obj.hexdigest() != expected_sha256: dst_stream.close() raise RuntimeError("文件读取失败,内容已被篡改") dst_stream.seek(0) return dst_stream
校验失败后可以加重试逻辑,多次重试失败再抛出错误即可。
方案4:文件锁(适合你可以管控所有写入该文件的进程的场景)
读取前给文件加共享读锁,所有写入进程修改文件前必须先拿到独占写锁,从根源上避免读写并发的问题。Unix平台可以用fcntl模块实现,Windows平台可以用win32file相关接口实现。
内容的提问来源于stack exchange,提问作者mangotango
相关产品推荐
相关产品推荐

