大文件三元组计算内存溢出及类型错误问题求助
解决大文件三元组计数的两个问题
第一个问题: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))
额外优化建议
- 打开文件时建议指定编码(比如
encoding='utf-8'),避免因文件编码问题导致的读取错误:with open('file.txt', 'r', encoding='utf-8') as file: - 写入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]) - 如果文件超级大,还可以考虑多进程/多线程处理,进一步提升速度,但单进程的生成器方式已经能解决内存问题了。
内容的提问来源于stack exchange,提问作者XTRUST.ORG
相关产品推荐
相关产品推荐

