一、文件操作核心逻辑:先理解“打开-操作-关闭”
Python操作文件遵循固定流程:
- 打开文件:通过
open()函数建立程序与文件的连接,返回“文件对象”(也称文件句柄); - 操作文件:通过文件对象执行读、写、追加等操作;
- 关闭文件:通过
close()方法释放文件资源(避免资源泄露、文件损坏)。
类比理解:操作文件就像操作水杯——打开文件=拿起水杯,读写=倒水/接水,关闭文件=放下水杯(不放下会占用手的资源)。
二、核心函数:open() 打开文件(必掌握)
open()是Python操作文件的入口函数,所有文件操作都从它开始,先掌握其语法和参数。
1. open() 基础语法
file_object = open(file, mode='r', encoding=None)
参数说明:
| 参数 | 作用说明 | 示例 |
|---|---|---|
| file | 必选参数,文件路径(绝对路径/相对路径) | './test.txt'、'/usr/data/log.txt' |
| mode | 可选参数,文件打开模式(默认r,只读),决定能对文件执行的操作 | 'r'(读)、'w'(写)、'a'(追加) |
| encoding | 可选参数,文件编码格式(文本文件必备,推荐utf-8) | encoding='utf-8' |
路径说明:
- 相对路径:以当前程序所在目录为基准,如
'test.txt'(程序同目录)、'./data/test.txt'(程序目录下的data文件夹); - 绝对路径:文件在系统中的完整路径,如Windows:
'C:\Users\admin\test.txt',Linux/Mac:'/home/admin/test.txt'(注意Windows路径需转义,或用r'C:\Users\admin\test.txt')。
2. 核心:文件打开模式(mode参数)
mode参数决定了文件的操作类型,新手最易混淆,以下是高频使用的模式及区别:
| 模式 | 中文说明 | 核心特性 | 适用场景 |
|---|---|---|---|
| r | 只读模式 | 默认模式,文件必须存在,否则报错;只能读取文件内容,不能修改 | 读取配置文件、日志文件 |
| w | 只写模式 | 文件不存在则创建,文件存在则清空原有内容;只能写入内容,不能读取 | 新建文件、覆盖写入数据 |
| a | 追加模式 | 文件不存在则创建,文件存在则在末尾追加内容;只能写入,不能读取 | 日志追加、数据补录 |
| r+ | 读写模式 | 文件必须存在,可同时读取和写入(写入会覆盖原有内容) | 读取并修改文件(需谨慎) |
| w+ | 写读模式 | 文件不存在则创建,清空原有内容;可先写后读 | 新建文件并验证写入内容 |
| a+ | 追加读模式 | 文件不存在则创建,在末尾追加内容;可追加后读取 | 追加数据后查看完整内容 |
| b | 二进制模式 | 与上述模式结合使用(如rb、wb),用于操作二进制文件(图片、视频、压缩包) | 读取/写入二进制文件 |
关键提醒:
- 文本文件(.txt、.py、.conf)操作需指定
encoding='utf-8',避免中文乱码; - 二进制文件(.jpg、.zip、.mp4)操作不能指定encoding,且模式需加
b(如rb)。
三、文件读取操作:从文件中获取内容
读取文件是最常用的操作,核心方法有read()、readline()、readlines(),按需选择。
1. 一次性读取全部内容(read())
适合小文件(几十KB内),一次性读取所有内容到字符串。
# 示例:读取文本文件
# 步骤1:打开文件(只读模式,指定utf-8编码)
f = open('./test.txt', mode='r', encoding='utf-8')
# 步骤2:读取全部内容
content = f.read()
print("文件全部内容:")
print(content)
# 步骤3:关闭文件(必须执行)
f.close()
2. 逐行读取(readline())
适合大文件,每次读取一行,避免一次性加载过多内容占用内存。
# 示例:逐行读取文件
f = open('./test.txt', mode='r', encoding='utf-8')
# 循环读取每一行,直到读取完毕(readline()返回空字符串表示结束)
print("逐行读取内容:")
while True:
line = f.readline()
if not line:
break
# 去除每行末尾的换行符(\n)
print(line.strip())
f.close()
3. 读取所有行到列表(readlines())
将文件每一行作为列表元素,方便遍历和索引。
# 示例:读取所有行到列表
f = open('./test.txt', mode='r', encoding='utf-8')
lines = f.readlines()
print("文件行列表:", lines) # 每行末尾带\n,如['第一行\n', '第二行\n']
# 遍历列表处理每行内容
print("处理后内容:")
for index, line in enumerate(lines):
print(f"第{index+1}行:{line.strip()}")
f.close()
4. 读取二进制文件(如图片)
# 示例:读取图片文件
f = open('./logo.jpg', mode='rb') # 二进制只读模式,无需encoding
img_data = f.read()
print(f"图片字节数:{len(img_data)}")
f.close()
# 写入新图片(验证读取内容)
f_new = open('./logo_copy.jpg', mode='wb')
f_new.write(img_data)
f_new.close()
四、文件写入操作:向文件中保存内容
写入文件需注意模式选择(w覆盖、a追加),核心方法是write()、writelines()。
1. 覆盖写入(mode='w')
文件不存在则创建,存在则清空原有内容,写入新内容。
# 示例:覆盖写入文本
f = open('./write_test.txt', mode='w', encoding='utf-8')
# 写入字符串
f.write("Python文件写入测试\n")
f.write("第二行内容\n")
# 关闭文件(写入后必须关闭,否则内容可能未保存)
f.close()
# 验证写入结果
f_read = open('./write_test.txt', mode='r', encoding='utf-8')
print("覆盖写入后的内容:")
print(f_read.read())
f_read.close()
2. 追加写入(mode='a')
在文件末尾添加内容,不覆盖原有内容。
# 示例:追加写入文本
f = open('./write_test.txt', mode='a', encoding='utf-8')
f.write("追加的第三行内容\n")
f.write("追加的第四行内容\n")
f.close()
# 验证追加结果
f_read = open('./write_test.txt', mode='r', encoding='utf-8')
print("追加写入后的内容:")
print(f_read.read())
f_read.close()
3. 写入多行(writelines())
将列表中的字符串逐行写入文件(需手动加换行符\n)。
# 示例:批量写入多行
lines = ["苹果\n", "香蕉\n", "橙子\n"]
f = open('./fruit.txt', mode='w', encoding='utf-8')
f.writelines(lines)
f.close()
# 验证结果
f_read = open('./fruit.txt', mode='r', encoding='utf-8')
print("批量写入后的内容:")
print(f_read.read())
f_read.close()
五、文件关闭:必须执行的收尾操作
打开文件后,若不执行close(),会导致:
- 文件资源被占用,其他程序无法操作该文件;
- 写入的内容可能未真正保存到磁盘(Python缓存机制);
- 长期运行的程序可能出现“文件句柄泄露”,导致系统资源耗尽。
1. 手动关闭(close())
最基础的方式,操作完成后显式调用close()。
f = open('./test.txt', mode='r', encoding='utf-8')
content = f.read()
f.close() # 手动关闭,必须写
2. 自动关闭(with语句,推荐)
Python提供with上下文管理器,代码块执行完毕后自动关闭文件,无需手动调用close(),是最安全的方式。
# 示例1:读取文件(自动关闭)
with open('./test.txt', mode='r', encoding='utf-8') as f:
content = f.read()
print("with语句读取内容:", content)
# 缩进结束后,文件已自动关闭
# 示例2:写入文件(自动关闭)
with open('./with_test.txt', mode='w', encoding='utf-8') as f:
f.write("使用with语句写入\n")
f.write("自动关闭文件,无需手动close")
# 验证写入结果
with open('./with_test.txt', mode='r', encoding='utf-8') as f:
print("with语句写入后的内容:")
print(f.read())
核心优势:即使代码块中出现异常(如读取时报错),with语句也会确保文件被关闭,避免资源泄露。
六、实战案例:文件操作高频场景
案例1:统计文件行数和字符数
# 统计test.txt的行数、总字符数(不含空格)
line_count = 0
char_count = 0
with open('./test.txt', mode='r', encoding='utf-8') as f:
for line in f: # 直接遍历文件对象,逐行读取(最省内存)
line_count += 1
# 去除空格和换行符后统计字符数
char_count += len(line.strip().replace(" ", ""))
print(f"文件总行数:{line_count}")
print(f"文件总字符数(不含空格):{char_count}")
案例2:批量替换文件中的指定内容
# 将test.txt中的"Python"替换为"Python3",保存到新文件
with open('./test.txt', mode='r', encoding='utf-8') as f_read, \
open('./test_new.txt', mode='w', encoding='utf-8') as f_write:
for line in f_read:
# 替换内容
new_line = line.replace("Python", "Python3")
# 写入新文件
f_write.write(new_line)
print("内容替换完成,新文件为test_new.txt")
案例3:读取大文件(GB级)的正确方式
大文件不能用read()一次性读取,需逐行遍历避免内存溢出:
# 读取GB级日志文件,筛选包含"ERROR"的行
with open('./big_log.log', mode='r', encoding='utf-8') as f:
with open('./error_log.log', mode='w', encoding='utf-8') as f_error:
for line in f:
if "ERROR" in line:
f_error.write(line)
print("ERROR日志已筛选到error_log.log")
七、常见问题与避坑指南
1. 中文乱码问题
- 原因:打开文件时未指定
encoding='utf-8',或文件本身编码不是utf-8; - 解决:
- 优先指定
encoding='utf-8'; - 若文件是GBK编码,改为
encoding='gbk'; - 用记事本打开文件,“另存为”选择utf-8编码。
- 优先指定
2. 文件不存在报错(FileNotFoundError)
- 原因:
r/r+模式下文件路径错误或文件不存在; - 解决:
- 检查文件路径(绝对路径/相对路径);
- 若允许创建文件,改用
w/a/w+/a+模式。
3. 写入内容不生效
- 原因:未关闭文件(缓存未刷新),或用
r模式写入; - 解决:
- 优先使用
with语句自动刷新缓存; - 手动写入后可调用
f.flush()强制刷新缓存; - 确认打开模式是
w/a/r+等可写入模式。
- 优先使用
4. 二进制文件操作报错
- 原因:操作二进制文件时指定了
encoding,或模式未加b; - 解决:二进制文件用
rb/wb/ab模式,且不指定encoding参数。