Python处理文本文件时write()从半程启动、lower()仅作用于部分内容的问题
异常的核心成因
问题根源是对Python文件对象的读写指针机制存在认知偏差,具体问题点:
- 用
r+模式打开文件时,读操作和写操作共享同一个文件指针,不存在“读到哪行就修改哪行再原位放回去”的逻辑 - 循环逐行读取的过程中,每读完一行,指针会自动移动到当前行的末尾位置;这时候直接调用
f.write(line),会从当前指针位置开始覆盖写入内容,直接打断后续的正常读取流程 - 实际运行的错位效果:假设文件总共有10行,读完第1行后指针停在第1行末尾,此时写入转换后的第1行内容,会直接覆盖从指针位置开始的后续内容,原来的第2行内容会被刚写入的内容替换,后续读取的行号完全错位,最终就会出现只有一半甚至更少的内容被转换的问题,严重时还会造成文件内容永久损坏。
另外代码本身存在两处隐藏缺陷:
- 用
glob匹配**/*.txt嵌套路径时,没有加recursive=True参数,默认不会递归扫描子文件夹内容,哪怕解决了指针问题,也会漏处理深层目录下的文本文件 - 导入的
os、string、re模块在当前逻辑中没有实际作用,属于冗余导入
常规场景的修复代码
针对常规大小的文本文件,用最稳妥的分读、转、写三步逻辑,从根本上避免读写指针冲突:
import glob # 增加recursive=True参数,确保递归扫描子文件夹下的txt文件 list_of_files = glob.glob("/Users/louis/Downloads/assignment/data2/**/*.txt", recursive=True) for file_name in list_of_files: # 以只读模式打开,全量读取文件内容到内存 with open(file_name, 'r', encoding='utf-8') as f: original_content = f.read() # 执行小写转换 lower_content = original_content.lower() # 以覆盖模式重新打开文件,写入转换后的全量内容 with open(file_name, 'w', encoding='utf-8') as f: f.write(lower_content)
这套写法的特性:
- 不存在指针错位问题,全量内容读取完成后再做转换,写回的时候完全覆盖原文件,不会出现只改一半的情况
- 显式指定
encoding='utf-8',避免不同操作系统默认编码差异导致的乱码问题 - 用
with上下文管理器打开文件,不需要手动编写关闭文件的代码,哪怕运行中途出现异常,也会自动释放系统的文件资源
大文件场景的适配方案
如果遇到单个体积特别大(GB级)、全量读进内存会造成内存占用过高的文本文件,不要强行使用全量读写的方式,改用临时文件中转的逻辑:
- 逐行读取原文件内容做转换,写入同目录下的临时文件
- 全部行处理完成后,删除原文件,把临时文件重命名为原文件的名称
这套逻辑不需要把全量内容加载进内存,也完全避免了同个文件对象读写的指针冲突问题。
内容的提问来源于stack exchange,提问作者Lodi1712
相关产品推荐
相关产品推荐

