Python 文件操作完整详解
核心概念 Python 文件操作核心基于内置 open() 函数,支持文本和二进制模式,配合 with 语句实现自动资源管理。
1. 文件操作核心基础
1.1. 核心内置函数 open()
Python 内置函数,用于打开文件,返回文件对象(file object),所有读写操作依托该对象完成。
1.1.1. 基础语法
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)
核心参数说明:
file:文件路径(相对路径/绝对路径)mode:打开模式(读/写/追加/二进制),默认r只读文本encoding:文本文件编码(utf-8/gbk,二进制模式无需传)errors:编码错误处理策略(strict抛异常、ignore忽略、replace替换乱码)newline:控制换行符转换(Windows\r\n/ Linux\n)
1.2. 推荐写法:with 上下文管理器(必用)
原生 open() 不手动 close() 会导致文件句柄泄露,with 语句自动关闭文件,异常也会自动释放资源,生产标准写法:
# 自动close,无需手动调用f.close()
with open("test.txt", "r", encoding="utf-8") as f:
data = f.read()
print(data)
# 代码块结束,文件自动关闭
2. 文件打开模式 mode 全分类
分为文本模式(t,默认)、二进制模式(b) 两大类,不能混用。
2.1. 文本模式(处理txt、md、csv等文字,自动编码转换)
| 模式 | 含义 | 文件不存在 | 文件存在 | 指针位置 |
r | read 只读(默认) | 抛 FileNotFoundError | 正常读取 | 文件开头 |
w | write 覆盖写 | 自动创建 | 清空全部内容再写入 | 文件开头 |
a | append 追加写 | 自动创建 | 保留原有内容,新增内容放末尾 | 文件末尾 |
r+ | 读写 | 报错 | 可读可覆盖写入 | 文件开头 |
w+ | 清空读写 | 创建 | 清空原有内容 | 文件开头 |
a+ | 追加读写 | 创建 | 可读,写入只能在末尾 | 文件末尾 |
2.2. 二进制模式(b,图片、视频、exe、压缩包、字节流,无编码)
在上面基础加 b:rb / wb / ab / rb+
- 读写返回
bytes字节对象,不能传 encoding 参数 - 不会自动转换换行符,原样读写二进制数据
示例:读取图片
with open("img.jpg", "rb") as f:
img_bytes = f.read()
2.3. 补充关键区分
r+:不会清空原文件,可修改中间内容;w+打开瞬间清空整个文件;a/a+无论怎么移动文件指针,write 写入永远追加到末尾;- 文本模式不加
t,默认就是rt;二进制必须显式写b。
3. 文件对象核心读写方法
3.1. (一)读取文件 3 种方法
3.1.1. read(size=-1):一次性读取全部内容
size:指定读取字节/字符数,默认-1读取全部- 文本模式返回字符串,二进制返回bytes
with open("test.txt", "r", encoding="utf-8") as f:
content = f.read() # 读取全部
part = f.read(100) # 读取前100个字符
缺点:超大文件一次性读入内存,易内存溢出。
3.1.2. readline():逐行读取,一次一行
末尾自带换行符 \n,无内容返回空字符串 ""
with open("test.txt", "r", encoding="utf-8") as f:
line1 = f.readline()
line2 = f.readline()
3.1.3. readlines():读取所有行,返回列表
每行作为列表元素,包含换行符,大文件不推荐
lines = f.readlines()
for line in lines:
print(line.strip())
3.1.4. 迭代器遍历(推荐,内存最优)
文件对象本身是可迭代对象,逐行加载,不一次性加载全文件:
with open("test.txt", "r", encoding="utf-8") as f:
for line in f:
real_line = line.strip() # 去除首尾换行空格
print(real_line)
3.2. (二)写入文件 2 种方法
3.2.1. write(str / bytes)
文本模式传入字符串,二进制传入bytes;不会自动添加换行符,需手动加 \n
with open("write.txt", "w", encoding="utf-8") as f:
f.write("第一行内容\n")
f.write("第二行内容\n")
返回值:写入的字符/字节数量。
3.2.2. writelines(可迭代对象)
接收列表、元组等序列,批量写入多行;同样不会自动换行
lines = ["苹果\n", "香蕉\n", "橙子\n"]
f.writelines(lines)
3.3. (三)文件指针控制(seek / tell)
文件内部有读写指针,标记当前读写位置。
f.tell():返回当前指针位置(字节偏移)f.seek(offset, whence):移动指针
-
offset:偏移量(正数向后,二进制模式支持负数) -
whence参考位置: -
0:文件开头(默认,文本模式仅支持0)
-
1:当前位置(仅二进制可用)
-
2:文件末尾(仅二进制可用)
示例:文本文件回到开头重新读取
with open("test.txt", "r", encoding="utf-8") as f:
print(f.read())
f.seek(0) # 指针移到文件头部
print(f.read())
示例:二进制读取最后100字节
with open("data.bin", "rb") as f:
f.seek(-100, 2)
last_data = f.read()
3.4. (四)其他常用方法
f.flush():强制把缓冲区内容刷入磁盘,不等待自动缓冲f.close():手动关闭文件(with 无需调用)f.closed:布尔值,判断文件是否已关闭f.name:获取打开的文件路径
4. 缓冲区 buffering 机制
文件读写不会直接操作磁盘,先存入内存缓冲区,满足条件才刷盘:
buffering=-1默认:文本行缓冲,二进制4096字节块缓冲buffering=0:二进制无缓冲,实时写入磁盘;文本模式不允许0buffering=1:文本行缓冲,遇到换行自动刷盘buffering=N:缓冲区达到N字节自动刷盘
手动强制落盘:f.flush()
5. os / pathlib 路径与文件系统操作(配套必备)
单纯 open 只负责读写,文件创建、删除、判断存在、遍历目录需要 os 或新标准库 pathlib。
5.1. pathlib(Python3.4+ 推荐,面向对象)
from pathlib import Path
# 1. 创建路径对象
p = Path("./test.txt")
# 判断
print(p.exists()) # 文件/目录是否存在
print(p.is_file()) # 是否是文件
print(p.is_dir()) # 是否是文件夹
# 创建/删除文件
p.touch() # 创建空文件
p.unlink() # 删除文件
# 目录操作
dir_p = Path("./data")
dir_p.mkdir(exist_ok=True) # 创建文件夹,存在不报错
dir_p.rmdir() # 删除空文件夹
# 遍历目录
for file in Path("./").iterdir():
print(file)
# 路径拼接
new_path = Path("./data") / "demo.txt"
5.2. os 模块(传统兼容写法)
import os
# 判断文件是否存在
os.path.exists("test.txt")
os.path.isfile("test.txt")
os.path.isdir("./dir")
# 创建/删除
os.makedirs("./data", exist_ok=True)
os.remove("test.txt") # 删除文件
os.rmdir("./data") # 删除空目录
# 遍历目录
os.listdir("./")
# 路径拼接(自动适配Windows/Linux分隔符)
file_path = os.path.join("./data", "1.txt")
6. 常见编码问题
- Windows 记事本默认编码
gbk,Linux/Mac 默认utf-8,不指定encoding极易乱码; - 报错
UnicodeDecodeError解决方案:
- 明确指定正确编码
encoding="gbk"/encoding="utf-8" - 容错读取:
errors="replace"乱码替换为�符号
# 兼容乱码文件
with open("gbk_file.txt", "r", encoding="gbk", errors="replace") as f:
pass
- 二进制模式无需编码参数,读写原始字节。
7. 超大文件高效读取方案
禁止一次性 read() 全量加载,两种方案:
- 迭代器逐行读取(文本日志首选)
with open("big_log.txt", "r", encoding="utf-8") as f:
for line in f:
process(line)
- 固定分块读取(二进制大文件、压缩包)
CHUNK_SIZE = 4096
with open("large.bin", "rb") as f_in, open("copy.bin", "wb") as f_out:
while chunk := f_in.read(CHUNK_SIZE):
f_out.write(chunk)
8. 高频坑点与避坑
8.1. 忘记关闭文件,句柄泄露
错误写法:
# 异常时无法close,长期运行打开文件数超限报错
f = open("1.txt", "r")
data = f.read()
# 忘记 f.close()
✅ 统一使用 with 上下文管理器。
8.2. w 模式误删原有数据
打开 w/w+ 瞬间清空文件,重要文件优先用 r+ 或 a。
8.3. 二进制/文本模式混用
图片、视频用 rb/wb,不能加 encoding;txt 文本不用 b 模式,否则读到bytes。
8.4. 相对路径歧义
程序运行目录不等于脚本所在目录,推荐使用绝对路径,或 __file__ 获取脚本真实路径:
from pathlib import Path
base = Path(__file__).parent # 当前脚本所在文件夹
file_path = base / "test.txt"
8.5. 多行写入忘记手动加 \n
write / writelines 不会自动换行,不添加换行所有内容挤在同一行。
8.6. a+ 模式指针陷阱
即使 seek(0) 移到开头,调用 write() 依然追加到文件末尾,无法中间插入内容。
9. 完整实战示例
9.1. 示例1:文本文件读写(with标准模板)
# 写入
with open("note.txt", "w", encoding="utf-8") as f:
f.write("Python 文件操作\n")
f.writelines(["第一行\n", "第二行\n"])
# 读取
with open("note.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip())
9.2. 示例2:二进制文件复制(图片/视频)
CHUNK = 8192
with open("source.jpg", "rb") as src, open("target.jpg", "wb") as dst:
while buf := src.read(CHUNK):
dst.write(buf)
9.3. 示例3:r+ 模式修改文件中间内容
注意:只能覆盖字节,无法插入文字(插入需要整体重写文件)
with open("demo.txt", "r+", encoding="utf-8") as f:
content = f.read()
f.seek(0)
f.write("【修改开头】\n" + content)
10. 面试核心速记总结
- 打开文件优先
with open()上下文管理器,自动释放句柄,杜绝泄露; - 模式区分文本(r/w/a/r+)、二进制(rb/wb/ab),二进制无encoding;
w清空文件,a末尾追加,r+可读可写不清空;- 读取:
read()全量、readline()单行、迭代器逐行(大文件最优); seek()移动文件指针,tell()查看当前偏移;- 超大文件分块/逐行读取,禁止一次性read占用内存;
- 路径操作新标准
pathlib,传统os.path兼容老项目; - 中文乱码根源:未指定encoding,Windows文件多为gbk,Linux为utf-8;
- 二进制模式支持seek负数偏移,文本模式仅支持从文件头偏移;
- write/writelines不会自动换行,需要手动拼接
\n。
关联文档