💾说明:几乎所有程序都需要与文件打交道——保存配置、记录日志、处理用户数据。本篇系统讲解 Python文件操作的核心方法,涵盖文本/二进制读写、路径处理、异常安全、编码问题及常用数据格式(CSV、JSON),助你写出可靠、跨平台、无乱码的文件处理代码。
你将掌握:
open()的正确用法与编码陷阱- 为什么必须用
with语句? - 读写 CSV 和 JSON 文件
- 处理大文件的高效策略
- 路径拼接的最佳实践(
pathlib)
1. 基础文件读写:open()与with
✅ 推荐写法:使用上下文管理器
# 写入文件withopen("hello.txt","w",encoding="utf-8")asf:f.write("你好,世界!")# 读取文件withopen("hello.txt","r",encoding="utf-8")asf:content=f.read()print(content)# 你好,世界!🔑关键点:
- 必须指定
encoding="utf-8"(避免 Windows 默认gbk导致乱码)- 永远用
with:自动关闭文件,即使出错也安全
2. 文件打开模式速查表
| 模式 | 含义 | 说明 |
|---|---|---|
'r' | 只读(默认) | 文件必须存在 |
'w' | 写入 | 覆盖原文件,不存在则创建 |
'a' | 追加 | 在文件末尾添加,不覆盖 |
'x' | 独占创建 | 文件存在则失败(防覆盖) |
'b' | 二进制模式 | 如'rb','wb' |
'+' | 读写 | 如'r+'(可读可写,不创建) |
示例:追加日志
withopen("app.log","a",encoding="utf-8")asf:f.write("[INFO] 程序启动\n")3. 读取文件的不同方式
| 方法 | 适用场景 |
|---|---|
f.read() | 一次性读取全部内容(小文件) |
f.readline() | 逐行读取(节省内存) |
f.readlines() | 读取所有行到列表(需随机访问行) |
for line in f | 推荐!高效逐行迭代(大文件) |
处理大文件(推荐方式)
# 安全处理 GB 级日志文件withopen("huge.log","r",encoding="utf-8")asf:forlineinf:# 一次只加载一行到内存if"ERROR"inline:print(line.strip())✅优势:内存占用恒定,不随文件大小增长。
4. 路径处理:告别字符串拼接!
❌ 错误做法(不可移植)
# Windows 用 \,Linux/Mac 用 /,极易出错!filepath="data"+"\\"+"input.txt"✅ 正确做法:使用pathlib(Python 3.4+)
frompathlibimportPath data_dir=Path("data")file_path=data_dir/"input.txt"# 自动适配操作系统# 检查并创建目录data_dir.mkdir(exist_ok=True)# 读取文件content=file_path.read_text(encoding="utf-8")💡
pathlib是现代 Python 文件路径操作的标准方式。
5. 数据持久化:JSON 与 CSV
5.1 JSON:结构化数据交换
importjsonfrompathlibimportPath# 写入data={"users":["Alice","Bob"],"version":1.0}Path("config.json").write_text(json.dumps(data,ensure_ascii=False,indent=2),encoding="utf-8")# 读取loaded=json.loads(Path("config.json").read_text(encoding="utf-8"))print(loaded["users"])# ['Alice', 'Bob']⚠️ 注意:
json只支持基本类型(dict,list,str,int,float,bool,None)
5.2 CSV:表格数据处理
importcsvfrompathlibimportPath# 写入 CSVwithopen("students.csv","w",newline="",encoding="utf-8")asf:writer=csv.writer(f)writer.writerow(["姓名","年龄","班级"])writer.writerow(["小明",18,"高三(1)班"])# 读取 CSV(推荐 DictReader)withopen("students.csv",encoding="utf-8")asf:reader=csv.DictReader(f)forrowinreader:print(f"{row['姓名']}-{row['班级']}")# 小明 - 高三(1)班🔑关键参数:
newline="":防止 Windows 多余空行DictReader:按列名访问,比索引更清晰
6. 二进制文件操作:图片、音频等
# 复制图片withopen("photo.jpg","rb")assrc:withopen("photo_copy.jpg","wb")asdst:dst.write(src.read())# 或用 shutil(更高效)importshutil shutil.copy2("photo.jpg","backup/photo_copy.jpg")✅ 二进制模式(
'rb','wb')不需要指定 encoding
7. 异常处理:让文件操作更健壮
frompathlibimportPathdefsafe_read_file(filepath):path=Path(filepath)try:ifnotpath.exists():raiseFileNotFoundError(f"文件不存在:{filepath}")returnpath.read_text(encoding="utf-8")exceptPermissionError:print("❌ 权限不足,无法读取文件")exceptUnicodeDecodeError:print("❌ 文件编码不是 UTF-8,请检查")exceptExceptionase:print(f"❌ 未知错误:{e}")returnNonecontent=safe_read_file("secret.txt")🛡️常见异常:
FileNotFoundErrorPermissionErrorIsADirectoryErrorUnicodeDecodeError(编码错误)
8. 实用技巧与最佳实践
| 场景 | 推荐方案 |
|---|---|
| 临时文件 | tempfile.NamedTemporaryFile() |
| 文件备份 | shutil.copy2(src, dst)(保留元数据) |
| 递归遍历目录 | Path.rglob("*.txt") |
| 获取文件大小 | Path("file.txt").stat().st_size |
| 安全写入(防中断损坏) | 先写临时文件,再重命名 |
安全写入示例(原子操作)
frompathlibimportPathimportosdefatomic_write(filepath,content):"""安全写入:避免程序崩溃导致文件损坏"""temp_path=Path(filepath).with_suffix(".tmp")try:temp_path.write_text(content,encoding="utf-8")os.replace(temp_path,filepath)# 原子替换exceptException:temp_path.unlink(missing_ok=True)# 清理临时文件raise9. 总结:文件操作黄金法则
- 永远用
with open(...) - 显式指定
encoding="utf-8"(文本文件) - 用
pathlib.Path处理路径 - 大文件用
for line in file逐行读取 - 结构化数据优先选 JSON/CSV
- 捕获并处理常见文件异常
💾记住:
“文件是程序与外部世界的桥梁,
安全、可靠、跨平台是你的责任。”
下一步练习
- 改造你的 To-Do List 项目:
- 用 JSON 保存任务列表
- 实现“自动备份”功能(每天生成
todo_backup_20251212.json)
- 编写一个日志分析脚本:
- 读取
app.log - 统计 ERROR 行数并输出到
error_report.txt
- 读取
- 尝试用 CSV 存储联系人,支持增删查改
🐍掌控文件,就是掌控数据。
你已具备构建完整本地应用的能力!
继续编码,让数据为你所用!