You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python大文件处理内存错误排查与低内存脚本优化咨询

问题分析与解决方案

我编写了一段Python脚本用于处理约64GB的超大文件testinp.txt,同时读取25-30MB的testinpmap.txt。脚本看似按行读取大文件,但执行时内存占用极高,最终触发MemoryError。以下是我的代码:

import re
h_file_name="testinp.txt" #This file is very large approx 64GB size
m_file_name="testinpmap.txt" #This files size is between 25-30MB
with open(h_file_name, "rb") as f, open(h_file_name+".re.txt", "wb+") as f1, open(m_file_name,"rb") as f2:
    req=""
    s=""
    cols1 = []
    for line in f:
        cols= re.split('[ ]+|[ ]+', line.strip())
        for i in range(len(cols)):
            if str(cols[i]).strip() == "1":
                cols[i] = "2"
        cols1.append(cols)
        for line2 in f2:
            cols2 = re.split('[ ]+|[ ]+', line2.strip())
            if (cols2[3].strip() != "."):
                for j in range(len(cols1[i])):
                    if str(cols1[i][j]).strip() == "0":
                        cols1[i][j] = "1"
    for c in cols1:
        req += " ".join(map(str,c))
        req += "\n"
    f1.write(req)

我疑惑为何按行读取仍会出现内存错误,且程序从执行开始就占用大量RAM,请问如何修改脚本以最小化内存占用并避免内存错误?


为什么你的脚本会爆内存?

核心问题是你没有真正做到“逐行处理后释放内存”,反而把所有数据都堆积在了内存里:

  • cols1列表会不断追加处理后的每一行数据,64GB的文件哪怕每行只有100字节,最终也会占用几十GB内存,直接触发MemoryError。
  • req变量会累加所有处理后的行内容,最后一次性写入文件,这又会额外占用大量内存。
  • 更糟的是,你在处理大文件的每一行时,都会完整遍历一遍testinpmap.txt(for line2 in f2),但文件指针读完一次后就会停在末尾,后续循环其实不会处理任何内容,还浪费了IO资源。
  • 正则表达式re.split('[ ]+|[ ]+')完全重复,简化成re.split(r'\s+')就可以(匹配任意空白字符)。

修改后的脚本(低内存版本)

我们的核心思路是:预加载小文件,逐行处理大文件,处理完一行就立刻写入输出文件,绝不把所有行存在内存里。

import re

h_file_name = "testinp.txt"
m_file_name = "testinpmap.txt"

# 第一步:预加载并处理map文件(25-30MB完全可以存在内存)
# 提取有效规则,避免重复读取文件
map_rules = []
with open(m_file_name, "rb") as f2:
    for line2 in f2:
        cols2 = re.split(r'\s+', line2.strip())
        # 二进制模式下字符串是bytes类型,要用b""匹配
        if cols2[3].strip() != b".":
            map_rules.append(cols2)

# 第二步:逐行处理大文件,处理完立刻写入输出
with open(h_file_name, "rb") as f, open(h_file_name + ".re.txt", "wb") as f1:
    for line in f:
        # 第一步替换:把1改成2
        cols = re.split(r'\s+', line.strip())
        for i in range(len(cols)):
            if cols[i].strip() == b"1":
                cols[i] = b"2"
        
        # 第二步应用map规则(修正原逻辑中的cols1[i]笔误,改用当前行的cols)
        for cols2 in map_rules:
            for j in range(len(cols)):
                if cols[j].strip() == b"0":
                    cols[j] = b"1"
        
        # 处理完立刻写入,不占用额外内存
        processed_line = b" ".join(cols) + b"\n"
        f1.write(processed_line)

关键优化点说明

  1. 预加载小文件:把testinpmap.txt的内容一次性加载到内存,避免在大文件的每行循环里重复读取,既节省IO资源,也减少重复加载的内存开销。
  2. 逐行处理+即时写入:处理大文件时,内存中只保留当前行的数据,处理完立刻写入输出文件,Python会自动回收这部分内存,内存占用会一直保持在很低的水平(仅当前行+map文件的内存)。
  3. 修正二进制字符串处理:因为你用了rb/wb模式,所有字符串都是bytes类型,所以要用b"1"、b"2"这种格式,避免类型不匹配的错误(原代码里str(cols[i])会把bytes转成b'1'格式的字符串,这是错误的)。
  4. 移除内存堆积变量:删掉cols1、req这些会累积数据的变量,从根源上避免内存溢出。

额外建议

  • 如果map文件规则可以简化(比如只需要特定字段),预加载时只提取需要的部分,进一步减少map_rules的内存占用。
  • 可以用line.split()(默认按任意空白分割)代替re.split,速度更快,内存占用更低。
  • 若需要更高效的处理,可考虑用pandas分块读取,但纯文本场景下,上面的逐行方法已经足够高效且内存友好。

内容的提问来源于stack exchange,提问作者user8393448

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:18:17