R / Richie全部文章 ↑

Python · 4 分钟阅读

Python:从文件逐行读取数据

目录


读取文本文件是 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"(默认):遇到坏字节抛 UnicodeDecodeError
  • errors="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 共享盘文件上读取时,设置合理超时(标准库无超时,可以用线程 + 超时包装)。