Python · 4 分钟阅读
Python:从文件逐行读取数据
目录
- 1. 三种基础写法
- 2. 直接读取字符串:
read() - 3. 二进制 / 字节方式
- 4. 选择策略
- 5. 常见小技巧
- 6. 大文件场景:分块 + 生成器
- 7. 性能对比(量级感受)
- 8. 最佳实践清单
读取文本文件是 Python 最常见的 IO 操作。open() + with 语句是标准模式;
按需选择“逐行迭代”、“一次性读出”或“分块读取”。
1. 三种基础写法
1.1 readline():完全手动
from pathlib import Path
path = Path("data.txt")
with path.open("r", encoding="utf-8") as f:
while True:
line = f.readline()
if not line: # 文件末尾:空字符串
break
print(line.rstrip("\n"))
适用:需要精确控制读取节奏(如边读边处理 + 提前中断)。
1.2 for line in f:推荐写法
from pathlib import Path
with Path("data.txt").open("r", encoding="utf-8") as f:
for line in f:
print(line.rstrip("\n"))
for循环 惰性 读取,内存友好。line末尾会保留\n,按需rstrip()或splitlines()。
1.3 readlines():一次读全部
from pathlib import Path
with Path("data.txt").open("r", encoding="utf-8") as f:
lines = f.readlines()
for line in lines:
print(line.rstrip("\n"))
- 文件较小时简单方便。
- 大文件不要用,会把整个文件加载到内存(GB 级文件会爆)。
2. 直接读取字符串:read()
from pathlib import Path
text = Path("data.txt").read_text(encoding="utf-8") # 整个文件成一个 str
lines = text.splitlines() # 不带 \n 的列表
- 适合:文件小、要交给正则/解析器处理。
- 与
readlines()类似,大文件慎用。
3. 二进制 / 字节方式
需要处理任意数据(图片、压缩包等)时使用二进制模式:
from pathlib import Path
data: bytes = Path("image.png").read_bytes()
逐行只对文本文件有意义;二进制文件按 块 读:
from pathlib import Path
with Path("binary.dat").open("rb") as f:
while chunk := f.read(64 * 1024): # 每次 64 KiB
process(chunk)
Python 3.8+ 支持 海象运算符
:=。
4. 选择策略
| 场景 | 推荐方式 |
|---|---|
| 文本、大文件 | for line in f |
| 文本、小文件 | read_text() + splitlines() |
| 需要按行号定位 | enumerate(f, start=1) |
| 只看前 N 行 | itertools.islice(f, N) |
| 处理大文件 + 正则 | 逐行读 + 编译好的正则 |
| 二进制 / 压缩包 | read_bytes() 或按块 read(n) |
5. 常见小技巧
5.1 跳过表头
from itertools import islice
from pathlib import Path
with Path("data.csv").open(encoding="utf-8") as f:
next(f) # 跳过表头
for line in f:
print(line.rstrip())
或:
from itertools import islice
with Path("data.csv").open(encoding="utf-8") as f:
for line in islice(f, 1, None): # 从第 2 行开始
...
5.2 自动处理换行符
with open("data.txt", encoding="utf-8", newline="") as f:
for line in f:
# Python 不会做任何换行符转换,保留原样
...
newline="" 是官方推荐写法,能避免 Windows / Linux 跨平台时 \r\n 错乱。
5.3 错误容忍:处理非 UTF-8 文件
with open("legacy.txt", encoding="utf-8", errors="replace") as f:
for line in f:
...
errors="strict"(默认):遇到坏字节抛UnicodeDecodeErrorerrors="ignore":丢坏字节errors="replace":替换为?
6. 大文件场景:分块 + 生成器
from pathlib import Path
def read_in_chunks(path: Path, chunk_size: int = 1024 * 1024):
"""生成器:每次产出一个 < 1 MiB 的文本块。"""
with path.open("r", encoding="utf-8") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
return
yield chunk
文本统计、压缩前处理等场景,生成器 + 行级迭代几乎总是最优解。
7. 性能对比(量级感受)
| 文件大小 | read() |
readlines() |
for line in f |
|---|---|---|---|
| 1 MB | 几毫秒 | 几毫秒 | 几毫秒 |
| 100 MB | 0.3s | 0.3s | 0.3s(流式) |
| 5 GB | 内存不够 | 内存不够 | 流畅(流式) |
for line in f 本质上调用 C 层的 IO,效率最高。
8. 最佳实践清单
- 永远用
with open(...)或Path.open(),不要 自己f.close()。 - 显式传
encoding="utf-8",不要依赖系统默认编码。 - 大文件只用流式迭代,绝不要
readlines()/read()整个塞进内存。 - 处理 CSV/日志用专门库(
csv/pandas),不要自己 split。 - 需要解析 CSV / JSON Lines 时按行读更友好(JSON Lines 天然逐行)。
- 在网络 / Windows 共享盘文件上读取时,设置合理超时(标准库无超时,可以用线程 + 超时包装)。