Python如何正确打开读取大文件?get_words_from_file函数排障
大文件运行失败修复方案
你的逐行读取文件逻辑本身是大文件友好的,不存在读取方式问题,故障来自三个逻辑漏洞,小测试用例刚好构造了完全匹配你硬编码规则的内容所以能正常运行,真实大文件场景下会触发问题:
- 起止边界判断逻辑错误:你硬编码要求行内容完全等于
*** START OF、*** END才触发标记切换,但实际通用的文本版权分隔行(比如古登堡计划电子书格式)在标记前缀后会带书名、项目编号等后缀,不会和你写的字符串完全相等,导致要么永远进不了正文读取分支,要么读到结束标记也不会终止,大文件下会无意义读取大量非目标内容,甚至触发内存异常。 - 缺少编码容错:大文件很容易混入无法被utf-8正常解码的特殊字符,没有容错配置的话遇到非法字节会直接抛出解码错误中断运行。
- 正则未预编译:每次处理行都重新解析正则规则,大文件下会产生不必要的性能损耗。
修复后可直接运行的代码
import re # 预编译正则,提升大文件处理效率 WORD_PATTERN = re.compile(r"[a-z]+[-'][a-z]+|[a-z]+[']?|[a-z]+") def get_words_from_file(filename): """返回感兴趣区域内的小写单词列表,自动过滤标点符号""" words = [] in_target_region = False # 增加解码容错,跳过无法识别的字符避免崩溃,逐行读取保留大文件内存友好特性 with open(filename, 'r', encoding='utf-8', errors='ignore') as file: for line in file: stripped_line = line.strip() # 用前缀匹配代替全字符串相等,适配真实文件的起止标记格式 if stripped_line.startswith("*** START OF"): in_target_region = True continue if stripped_line.startswith("*** END OF"): break if in_target_region: lower_line = line.lower() words.extend(WORD_PATTERN.findall(lower_line)) return words
额外说明
- 不要改成
file.read()一次性读取全文件的写法,那种方式才会在GB级大文件下占满内存触发崩溃,你原来的逐行迭代逻辑是处理大文件的最优写法,只需要修复判断逻辑即可。 - 如果你的测试文件里结束标记是其他格式,只需要调整
startswith里的匹配前缀即可,不需要写全整行内容。
内容的提问来源于stack exchange,提问作者Hugo Smith
相关产品推荐
相关产品推荐

