文件模式详解:r、w、a、r+、w+、a+ 模式的区别与使用场景

说实话,刚学文件操作那会儿,我也被这六个模式搞得晕头转向。r、w、a 还好理解,一加上加号就懵了。今天咱们就把它们彻底捋清楚。

先看一张图,心里有个谱

下面这张 SVG 图,是我自己画的知识结构。你看完它,再往下读,会轻松很多。

Python 文件打开模式总览 基础模式 r 只读(文件必须存在) w 只写(清空/新建) a 追加(文件指针在末尾) 增强模式(可读可写) r+ 读写(文件必须存在) w+ 读写(清空/新建) a+ 读写(追加模式) 加 + 号 核心记忆点 r 系列:文件必须存在 | w 系列:会清空文件 | a 系列:永远在末尾写

基础模式:r、w、a

这三个模式,是文件操作的「三原色」。搞懂它们,加号模式自然就通了。

r 模式(只读)

这个最简单。打开文件只能读,不能写。文件不存在就报错。我平时读配置文件、日志文件,都用它。

# 读取一个文本文件
with open('config.txt', 'r', encoding='utf-8') as f:
    content = f.read()
    print(content)
注意:文件不存在时,会抛出 FileNotFoundError。我曾经在自动化脚本里忘了检查文件是否存在,结果半夜报警,爬起来一看,原来是路径写错了。

w 模式(只写)

这个模式有点「暴力」。它会先清空文件内容,再写入。如果文件不存在,它会新建一个。说白了,就是「从头来过」。

# 写入新内容,旧内容会被清空
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write('这是新内容')
我的习惯:每次用 w 模式前,我都会确认一下是不是真的要覆盖。尤其是操作生产环境的文件时,我会先备份。

a 模式(追加)

这个模式很「温柔」。它不会清空文件,而是把新内容写在文件末尾。文件不存在时也会新建。我常用它来写日志。

# 追加内容到文件末尾
with open('log.txt', 'a', encoding='utf-8') as f:
    f.write('2024-01-01: 用户登录成功\n')

你想想看,如果日志用 w 模式,每次启动程序就把之前的日志全清了,那还查什么历史记录?

增强模式:r+、w+、a+

加号的意思是「加上写权限」。但具体怎么加,每个模式都不一样。

模式 文件必须存在? 是否清空? 指针初始位置 典型场景
r+ 是 否 文件开头 修改文件中的某一部分
w+ 否 是 文件开头(空文件) 读写新文件
a+ 否 否 文件末尾 读取并追加日志

r+ 模式(读写,不覆盖)

这个模式有点「讲究」。它不会清空文件,你可以读,也可以写。但写的时候,是从当前指针位置开始覆盖。嗯,这里要注意:如果你先读后写,指针已经跑到末尾了,写的内容就追加到末尾了。

# 修改文件中的前几个字符
with open('data.txt', 'r+', encoding='utf-8') as f:
    content = f.read()  # 读完,指针在末尾
    f.seek(0)           # 把指针移回开头
    f.write('新内容')    # 从开头覆盖写入
避坑指南:我曾经用 r+ 模式想修改文件中间的内容,结果忘了移动指针,直接写到了末尾。后来我养成了习惯:用 r+ 时,一定先用 seek() 定位。

w+ 模式(读写,清空)

这个模式就是 w 的升级版。它会清空文件,然后你可以读写。但说实话,我很少用 w+。因为既然都清空了,读出来的也是空内容,还不如直接用 w 写,需要读的时候再单独打开。

# w+ 模式:先清空,再写入,最后读取
with open('temp.txt', 'w+', encoding='utf-8') as f:
    f.write('临时数据')
    f.seek(0)  # 写完后指针在末尾,需要移回开头才能读
    print(f.read())

我个人习惯,只有在需要「先写后读」的临时文件场景下,才会用 w+。

a+ 模式(读写,追加)

这个模式很有意思。它不会清空文件,写的时候永远在末尾追加。但读的时候,你可以通过 seek() 移动到任意位置读取。不过要注意,写操作不受 seek() 影响,永远追加在末尾。

# a+ 模式:先读取全部内容,再追加新内容
with open('history.log', 'a+', encoding='utf-8') as f:
    f.seek(0)  # 移到开头才能读取
    old_content = f.read()
    print('历史内容:', old_content)
    
    f.write('新记录\n')  # 自动追加到末尾
小技巧:用 a+ 模式时,如果想读取最新写入的内容,记得先 flush() 或 close() 再打开。因为写入的内容可能还在缓冲区里。

如何选择?我的经验总结

  • 只是读文件 → 用 r。简单、安全,不会误写。
  • 从头写一个新文件 → 用 w。省心,自动创建。
  • 追加日志、记录 → 用 a。不会丢失历史数据。
  • 需要修改文件中的某部分 → 用 r+。但记得用 seek() 控制指针。
  • 先写后读的临时文件 → 用 w+。虽然场景不多,但确实有用。
  • 既要追加又要读取历史 → 用 a+。注意指针位置。

最后说一句:文件操作看似简单,但坑不少。尤其是指针位置,稍不注意就出 bug。我建议你写代码时,多打印一下 tell() 看看指针在哪,心里就有数了。

可可精品资料库