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 用起来,准没错。