4、文件操作基础:打开与关闭文件、读取文件内容、写入文件内容、with语句

文件操作,说白了就是让程序和硬盘上的文件「对话」。我刚开始写自动化脚本时,觉得这玩意儿特简单——不就是读读写写嘛。结果呢?有一次脚本跑了一整夜,第二天发现日志文件没关,把服务器磁盘撑爆了。嗯,从那以后我再也不敢小看文件操作了。

4.1 打开与关闭文件:基本功,但别翻车

Python 里打开文件用 open() 函数。它的基本用法是:

file = open('test.txt', 'r')  # 'r' 表示只读模式
# 干点啥...
file.close()                  # 用完记得关

这里有个坑——忘记关闭文件。我见过不少新手,打开文件后直接开始读写,完事就跑了。文件对象会一直占用系统资源,轻则内存泄漏,重则文件损坏。

常用的文件打开模式,我整理了一张表:

模式 含义 文件存在时 文件不存在时
'r' 只读 正常打开 报错
'w' 只写 清空内容 创建新文件
'a' 追加 末尾追加 创建新文件
'r+' 读写 正常打开 报错
'w+' 读写 清空内容 创建新文件
'a+' 读写追加 末尾追加 创建新文件
注意:'w' 模式要格外小心。我曾经在调试脚本时,不小心把配置文件的路径写错了,结果 'w' 模式直接把生产环境的日志文件清空了……那叫一个惨。

4.2 读取文件内容:三种姿势,各有千秋

文件打开后,怎么读?我一般用这三种方法:

4.2.1 read() —— 一口闷

with open('data.txt', 'r') as f:
    content = f.read()      # 一次性读完整个文件
    print(content)

适合小文件。如果文件有几百兆,你想想看,一口气读到内存里,机器不卡才怪。

4.2.2 readline() —— 一行一行来

with open('data.txt', 'r') as f:
    line = f.readline()     # 只读第一行
    while line:
        print(line.strip()) # strip() 去掉换行符
        line = f.readline()

适合逐行处理。比如日志分析,一行一条记录,用这个最合适。

4.2.3 readlines() —— 全收进列表

with open('data.txt', 'r') as f:
    lines = f.readlines()   # 返回一个列表,每行是一个元素
    for line in lines:
        print(line.strip())

我个人习惯用 readlines(),因为方便索引。比如我想看第 5 行,直接 lines[4] 就行。

小技巧: 其实最 Pythonic 的方式是直接遍历文件对象:for line in f:。它内部做了缓冲,既省内存又高效。我在处理 2GB 的日志文件时,就用这个方式,稳得很。

4.3 写入文件内容:写对了,数据才安全

写入文件,核心就两个模式:'w''a'

4.3.1 覆盖写入('w'

with open('output.txt', 'w') as f:
    f.write('第一行内容\n')
    f.write('第二行内容\n')

注意:write() 不会自动加换行符,你得自己加 \n。我刚开始写的时候,经常忘了加,结果所有内容挤在一行,那叫一个乱。

4.3.2 追加写入('a'

with open('log.txt', 'a') as f:
    f.write('2024-01-01 新记录\n')

适合写日志。每次运行脚本,往文件末尾加一条记录,不会覆盖之前的内容。

核心要点: 写入时一定要确认模式。我曾经在写自动化测试报告时,用了 'w' 模式,结果每次运行都覆盖了上一次的报告。后来改成 'a' 模式,才把历史记录保留下来。

4.4 with 语句:优雅又安全

前面说了,手动 close() 容易忘。Python 提供了 with 语句,自动帮你处理关闭操作。

with open('test.txt', 'r') as f:
    content = f.read()
# 出了 with 块,文件自动关闭

为什么推荐用 with

  • 自动关闭:不管代码里有没有异常,文件都会正常关闭。
  • 代码简洁:少写一行 close(),少一个出错机会。
  • 上下文管理with 是 Python 的上下文管理器,不仅用于文件,还能用于数据库连接、锁等场景。
我的习惯: 只要涉及文件操作,我必用 with。哪怕只是读一个几 KB 的小文件,也绝不偷懒。为什么?因为习惯一旦养成,就不会在关键时刻掉链子。

4.5 避坑指南

最后,分享几个我踩过的坑:

  • 编码问题:读取中文文件时,记得指定 encoding='utf-8'。否则会报 UnicodeDecodeError。我曾经因为这个,排查了半天。
  • 路径问题:Windows 用反斜杠 \,Linux 用正斜杠 /。建议用 os.path.join() 拼接路径,跨平台无压力。
  • 大文件处理:别用 read() 读大文件。用 for line in f 逐行处理,内存占用小。
  • 文件不存在:读文件前,最好用 os.path.exists() 检查一下。否则 open() 会直接抛异常。

文件操作,看似简单,但细节决定成败。你想想看,一个自动化脚本跑几个小时,最后因为文件没关好导致数据丢失,那得多郁闷。所以,with 用起来,准没错。