欢迎来到 Python 学习计划的第 62 天!🎉
昨天我们学习了 异常链 (raise ... from ...),掌握了如何保留原始错误信息。从今天开始,我们将学习 Python 工程化开发的另一项核心技能——文件操作。
文件读写是程序与外部世界交互的基础。今天我们先学习 如何安全地读取文件。
一、open() 函数详解
1. 基本语法
file = open(file, mode='r', buffering=-1, encoding=None, ...)
2. 核心参数
参数 | 说明 | 示例 |
|---|
file
| 文件路径 | "data.txt"
|
mode
| 打开模式 | "r", "rb", "r+"
|
encoding
| 编码格式 | "utf-8", "gbk"
|
errors
| 错误处理 | "strict", "ignore"
|
3. 常用打开模式
模式 | 说明 | 文件不存在 |
|---|
"r"
| 只读(文本) | 报错 |
"rb"
| 只读(二进制) | 报错 |
"r+"
| 读写(文本) | 报错 |
"w"
| 写入(覆盖) | 创建 |
"a"
| 追加写入 | 创建 |
4. 基本示例
# 读取文本文件withopen("data.txt", "r", encoding="utf-8") as f: content = f.read()# 读取二进制文件withopen("image.png", "rb") as f: data = f.read()
💡 最佳实践:始终使用 with 语句,它会自动调用 close(),即使发生异常也能确保文件关闭。
二、读取方法对比
Python 提供了三种主要的读取方法,适用于不同场景。
1. read() - 读取全部
withopen("data.txt", "r", encoding="utf-8") as f: content = f.read() # 读取全部内容 content = f.read(100) # 读取 100 个字符
特点 | 说明 |
|---|
优点 | 简单直接,一次性获取全部内容 |
缺点 | 大文件会占用大量内存 |
适用 | 小文件(< 10MB) |
2. readline() - 逐行读取
withopen("data.txt","r", encoding="utf-8")as f:
line1 = f.readline()# 读取一行
line2 = f.readline()# 读取下一行
特点 | 说明 |
|---|
优点 | 内存占用小 |
缺点 | 需要循环调用 |
适用 | 按行处理的文件 |
3. readlines() - 读取所有行
withopen("data.txt", "r", encoding="utf-8") as f: lines = f.readlines() # 返回列表,每行一个元素
特点 | 说明 |
|---|
优点 | 内存占用小 |
缺点 | 需要循环调用 |
适用 | 按行处理的文件 |
3. readlines() - 读取所有行
withopen("data.txt","r", encoding="utf-8")as f:
lines = f.readlines()# 返回列表,每行一个元素
特点 | 说明 |
|---|
优点 | 方便遍历和处理 |
缺点 | 所有行加载到内存 |
适用 | 中等大小文件 |
4. 方法对比表
方法 | 返回值 | 内存占用 | 适用场景 |
|---|
read()
| str
| 高 | 小文件 |
readline()
| str
| 低 | 大文件逐行处理 |
readlines()
| list[str]
| 高 | 需要随机访问行 |
三、大文件读取最佳实践
1. 推荐:直接迭代文件对象
这是最 Pythonic 的方式,内存效率最高。
with open("large_file.txt", "r", encoding="utf-8") as f: for line in f: # 每次只读取一行 process(line)
2. 分块读取
适合二进制文件或需要控制读取量的场景。
def read_in_chunks(filepath, chunk_size=1024): with open(filepath, "rb") as f: while chunk := f.read(chunk_size): process(chunk)read_in_chunks("large_video.mp4")
3. 性能对比
import time# 方式 1:read() - 最慢(大文件)start = time.time()with open("1GB.txt") as f: content = f.read()print(f"read(): {time.time() - start:.2f}s")# 方式 2:迭代 - 最快start = time.time()with open("1GB.txt") as f: for line in f: passprint(f"迭代:{time.time() - start:.2f}s")
四、编码问题处理
1. 常见编码格式
编码 | 说明 | 适用 |
|---|
utf-8
| 通用编码 | 推荐默认使用 |
gbk
| 中文编码 | 旧 Windows 系统 |
latin-1
| 单字节编码 | 欧洲语言 |
2. 编码错误处理
# 严格模式(默认)- 遇到错误抛异常open("file.txt", encoding="utf-8", errors="strict")# 忽略错误 - 跳过无法解码的字符open("file.txt", encoding="utf-8", errors="ignore")# 替换错误 - 用替换无法解码的字符open("file.txt", encoding="utf-8", errors="replace")
3. 检测文件编码
import chardetdef detect_encoding(filepath): with open(filepath, "rb") as f: result = chardet.detect(f.read(10000)) # 检测前 10KB return result["encoding"]encoding = detect_encoding("unknown.txt")print(f"文件编码:{encoding}")
总结
知识点 | 说明 |
|---|
open() | 打开文件,指定模式、编码等参数 |
read() | 读取全部内容,适合小文件 |
readline() | 逐行读取,内存效率高 |
readlines() | 读取所有行到列表 |
with 语句 | 自动管理文件关闭,推荐使用 |
编码 | 明确指定 encoding="utf-8" |
大文件 | 使用迭代方式 for line in f |
📌 明日预告:文件写入与编码问题
明天我们将进入 异常与文件模块第八天!
- 主题:文件写入与编码问题
- 核心问题:
- 写入模式(w, a, x)有什么区别?
write() 和 writelines() 怎么用?- 写入时如何处理编码问题?
- 如何避免覆盖重要文件?
- 换行符在不同系统上有什么区别?
💡 提前思考:
w 模式和 a 模式的最大区别是什么?- 写入中文时为什么会乱码?
- 如何安全地写入文件(防止数据丢失)?
掌握文件读取,是数据处理的第一步!明天学习如何安全写入!继续加油!🚀