1. 文件操作是什么? #
- 全栈开发里经常要在磁盘上读写数据:应用日志、配置文件、导出 CSV、缓存 JSON、处理用户上传文件等。
- Python 用内置
open() 或标准库 pathlib 操作文件与路径。
- 务必用
with 打开文件,离开代码块自动 close,异常时也不会泄漏句柄。
- 读写文本文件时指定
encoding="utf-8",避免中文乱码和跨平台编码不一致。
- 二进制(图片、部分 Excel)用
rb/wb,不必指定文本编码。
2. 打开文件与模式 #
open(路径, mode, encoding=...) 返回文件对象。
- 模式决定读、写、追加还是二进制;路径可以是相对路径(相对当前工作目录)或绝对路径。
- 打开后常用
read()、for line in f、write() 等方法。
- 模式选错会导致覆盖原文件或无法写入。
- 写日志用
a、生成新报告用 w、只读配置用 r。
with open("access.log", "r", encoding="utf-8") as f:
print(f.read())
with open("out.log", "a", encoding="utf-8") as f:
f.write("new line\n")
| 模式 |
含义 |
项目场景 |
r |
只读,文件须存在 |
读配置、日志 |
w |
覆盖写,不存在则创建 |
生成报告、导出 |
a |
末尾追加 |
写日志 |
rb / wb |
二进制读写 |
图片、Excel 二进制 |
write() 不会自动换行,每行末尾需自己加 \n。
writelines() 同样不会替你补换行。
3. 读取 #
- 按文件大小选策略:小文件(配置、几 KB 的 mock 数据)可
read() 一次读完。
- 大文件(访问日志、导出流水)应
for line in f 逐行读,利用迭代器惰性读取。
- 避免
read() / readlines() 把整个文件塞进内存,与迭代器章节同一思路。
3.1 小文件:一次读完 #
- 配置文件、短文本、测试用的 fixture 适合
f.read() 得到完整字符串。
- 再
json.loads 或按行 split 处理。
with open("config.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
3.2 大文件:逐行(推荐) #
- 日志分析、大批量导入时,
for line in f 每次只处理一行,内存占用稳定。
- 可在循环内
strip()、过滤空行、解析 JSONL 等。
with open("access.log", "r", encoding="utf-8") as f:
for line in f:
print(line)
4. 写入 #
- 写入用模式
w(覆盖,文件不存在则创建)或 a(在末尾追加,适合日志)。
f.write(字符串) 写入文本;多行可循环 write,或用 writelines(行列表) 一次写入。
- 列表里每行通常已带
\n。
- 覆盖写会清空原内容,生产脚本里对路径要格外确认,避免误删重要文件。
lines = ["row1\n", "row2\n"]
with open("report.txt", "w", encoding="utf-8") as f:
f.write("标题\n")
for line in lines:
f.write(line)
with open("report.txt", "w", encoding="utf-8") as f:
f.writelines(lines)
5. with 语句(必用) #
with open(...) as f: 是上下文管理器写法:进入 with 时打开文件。
- 正常结束或抛异常离开
with 时都会自动 close(),比手动 f.close() 安全。
- 未关闭的文件在 Windows 上可能被占用导致无法删除或二次打开。
- 长驻进程里泄漏句柄还会拖垮服务。
- 项目里一律用
with,不要裸 open 后忘记关闭。
with open("data.txt", "r", encoding="utf-8") as f:
data = f.read()
6. pathlib(现代写法,可选) #
pathlib.Path 把路径拼接、判断存在、读写文本合成面向对象的 API。
- 如
Path("a") / "b" / "c.txt"、read_text() / write_text()。
- 适合本地脚本、小工具、一次性数据处理。
- Web 项目里框架上传、配置仍常见
open()。
- 需要跨平台拼路径、少写
os.path.join 时可优先 pathlib。
from pathlib import Path
text = Path("config.json").read_text(encoding="utf-8")
print(text)
Path("out.txt").write_text("hello\n", encoding="utf-8")
7. JSON 与 CSV #
- 结构化数据落盘最常见两种格式:JSON(配置、接口 mock、缓存)与 CSV(表格导出、Excel 可打开的报表)。
- JSON 用标准库
json:dump/load 与文件对象配合。
- CSV 用
csv 模块的 reader/writer。
- 写 CSV 在 Windows 上建议
open(..., newline=""),避免多余空行。
import json
data = {"name": "张三", "roles": ["admin"]}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("data.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
import csv
with open("users.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["name", "age"])
writer.writerow(["Alice", 25])
with open("users.csv", "r", newline="", encoding="utf-8") as f:
for row in csv.reader(f):
print(row)
8. 常见异常 #
- 文件操作失败时常见三类异常:路径不存在、权限不足、编码不匹配。
- 脚本与接口层应对可预期情况做
try/except 或先判断 Path.exists(),给用户明确提示,而不是直接 500。
- 生产环境还要注意磁盘满、文件被其他进程占用等运维问题。
| 异常 |
常见原因 |
FileNotFoundError |
路径错、文件不存在 |
PermissionError |
无读写权限、文件被占用 |
UnicodeDecodeError |
编码与文件不一致,改 encoding 或先确认文件编码 |
try:
with open("missing.txt", "r", encoding="utf-8") as f:
print(f.read())
except FileNotFoundError:
print("文件不存在")
9. 项目开发要点 #
- 文件 I/O 看似简单,模式选错、编码不对、大文件一次读入是常见线上隐患。
- 一律
with open(...),文本加 encoding="utf-8"。
- 日志、大文件用
for line in f,避免 read() / readlines() 爆内存。
- 写日志用
a,生成新文件用 w,别搞混。
- 配置与 API 数据用
json;表格导出用 csv。
- 生产环境路径用配置项或
pathlib / os.path.join,不要硬编码绝对路径。
- 敏感文件(密钥、
.env)不要提交仓库;读写前检查权限与路径。
10. 总结 #
- 文件操作记住:
with + 正确模式 + UTF-8 文本编码。
- 大文件逐行读;结构化数据用 json/csv。
- 下表按场景速查常用写法。
| 操作 |
写法 |
| 读小文件 |
with open(...) as f: f.read() |
| 读大文件 |
for line in f: |
| 写/追加 |
w / a + f.write(...\n) |
| 二进制 |
rb / wb |
| 结构化 |
json.load / dump,csv.reader / writer |