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

大文件三元组计算内存溢出及类型错误问题求助

解决大文件三元组计数的两个问题

第一个问题:MemoryError(处理大文件时内存溢出)

你原来的代码用file.read()一次性把几GB的文件全部读进内存,内存直接不够用,所以触发了MemoryError。

解决办法是逐行读取文件,配合生成器逐token处理,用滑动窗口(deque)维护三元组的上下文,这样每次只在内存里保留少量数据,不会撑爆内存。


第二个问题:TypeError: unhashable type: 'list'

你修改后的生成器返回的是list类型的三元组,但Counter的键必须是可哈希的类型(比如元组、字符串),列表是可变的,不能作为字典/Counter的键,所以报错。

解决办法很简单:把生成器里的yield list(fifo)改成yield tuple(fifo),元组是不可变且可哈希的,完美适配Counter。


修复后的完整代码

import sys
import string
from nltk.tokenize import RegexpTokenizer
from collections import deque, Counter

tokenizer = RegexpTokenizer(r'\w+')

def ngram_iter(it, n=3):
    fifo = deque(maxlen=n)
    for line in it:
        for token in tokenizer.tokenize(line):
            fifo.append(token)
            if len(fifo) == n:
                # 把列表换成元组,满足可哈希要求
                yield tuple(fifo)

# 逐行读取大文件,避免内存溢出
with open('file.txt', 'r') as file:
    count = Counter(ngram_iter(file, 3))

# 写入结果到CSV
with open('out_2.csv','w') as csvfile:
    for tag, freq in count.items():  
        csvfile.write('{},{},{},{}\n'.format(tag[0], tag[1], tag[2], freq))

额外优化建议

  1. 打开文件时建议指定编码(比如encoding='utf-8'),避免因文件编码问题导致的读取错误:
    with open('file.txt', 'r', encoding='utf-8') as file:
    
  2. 写入CSV时用csv.writer代替手动拼接字符串,能避免内容里有逗号导致的格式混乱:
    import csv
    with open('out_2.csv','w', newline='', encoding='utf-8') as csvfile:
        writer = csv.writer(csvfile)
        # 可以加个表头
        writer.writerow(['第一个词', '第二个词', '第三个词', '出现次数'])
        for tag, freq in count.items():
            writer.writerow([tag[0], tag[1], tag[2], freq])
    
  3. 如果文件超级大,还可以考虑多进程/多线程处理,进一步提升速度,但单进程的生成器方式已经能解决内存问题了。

内容的提问来源于stack exchange,提问作者XTRUST.ORG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:50:02