逐行读取大文件到第32671363行出现MemoryError,如何定位问题原因?
故障定位方法
- 排查换行符丢失导致的超大行问题
逐行读取逻辑默认以\n作为行分隔符,若32671363行之后的内容丢失了换行符,Python会将后续所有文件内容读取到同一个字符串变量中直到找到下一个换行符,直接触发内存溢出。可以通过以下代码验证:
# 先定位32671363行结束的文件偏移位置 offset = 0 with open('filename.txt', 'rb') as f: for line_num in range(32671364): line = f.readline() if line_num == 32671363: offset = f.tell() break # 从偏移位置读取固定大小块检查换行符 with open('filename.txt', 'rb') as f: f.seek(offset) # 单次读取1MB,远大于正常业务行的长度 chunk = f.read(1024 * 1024) if b'\n' not in chunk: print("存在无换行超长坏块,故障原因为换行符丢失") else: print(f"下一个换行符距离报错行结束位置{chunk.index(b'\n')}字节,该行长度正常")
- 排查异常编码/特殊字符问题
如果换行符存在,可读取异常行的二进制内容排查编码错误或特殊控制字符:
with open('filename.txt', 'rb') as f: f.seek(offset) # 最多读取10MB内容找下一个换行 bad_line_content = b'' while True: byte = f.read(1) if byte == b'\n' or len(bad_line_content) > 10 * 1024 * 1024: break bad_line_content += byte # 打印前100字节的十六进制编码查看异常 print("异常行前100字节十六进制:", bad_line_content[:100].hex()) # 替换为你的文件实际编码(如gbk、utf-8)尝试解码 try: print("解码结果:", bad_line_content.decode('utf-8')) except UnicodeDecodeError as e: print(f"解码错误位置:{e.start},错误字节内容:{bad_line_content[e.start:e.end].hex()}")
- 提取局部坏块直接查看
不用打开整个14GB文件,可提取报错位置前后的小范围内容单独分析:
Linux环境可使用dd命令提取:
# 替换为上一步得到的实际offset值,提取offset前后各5MB内容到小文件 dd if=filename.txt of=bad_part.bin bs=1 skip=$((offset - 5*1024*1024)) count=$((10*1024*1024))
Windows环境可使用WinHex等工具直接跳转到对应offset位置查看内容。
内容的提问来源于stack exchange,提问作者nuki
相关产品推荐
相关产品推荐

