不能直接用 json.load() 读 JSONL 文件,因为 JSONL 每行一个独立 JSON 对象,而 json.load() 期望整个文件为单个 JSON 值,遇换行或第二个 { 就报 JSONDecodeError;必须逐行用 json.loads() 解析,并注意编码、空行、异常处理及流式读取。

为什么不能直接用 json.load() 读 JSONL 文件?
JSONL 不是标准 JSON,而是每行一个独立的 JSON 对象,json.load() 会尝试解析整个文件为单个 JSON 值,遇到换行或第二个 { 就报 JSONDecodeError: Extra data。这不是数据问题,是解析器预期不匹配。
- JSONL 必须逐行解析,每行调用一次
json.loads() - 千万别用
json.load(open("file.jsonl")),它必然失败 - 如果文件很大(GB 级),一次性
readlines()会吃光内存,得用生成器流式读取
如何安全高效地逐行读取 JSONL?
用普通文件迭代 + json.loads() 是最轻量、兼容性最好的方式。关键在异常处理和编码控制:
- 使用
with open(... , encoding="utf-8") as f:显式指定编码,避免 Windows 默认cp1252解码失败 - 每行用
line.strip()清除空行和换行符,防止json.loads("")报错 - 包裹
try/except json.JSONDecodeError,打印出错行号(enumerate(f, 1))便于定位脏数据
def read_jsonl(path):
with open(path, encoding="utf-8") as f:
for i, line in enumerate(f, 1):
line = line.strip()
if not line:
continue
try:
yield json.loads(line)
except json.JSONDecodeError as e:
print(f"Parse error at line {i}: {e}")
写入 JSONL 时最容易踩的三个坑
写 JSONL 看似简单,但生产环境常因细节翻车:
- 每个对象必须单独成行,结尾不能有多余空格或换行 —— 用
json.dumps(obj, separators=(",", ":"))控制空白,避免默认缩进或空格干扰下游解析 - 写入时没加换行符,所有对象挤在一行,变成非法 JSONL —— 每次
f.write(... + "\n"),不能依赖print(..., file=f)(可能带额外空格) - 多进程/多线程并发写同一个文件,导致行断裂 —— JSONL 不支持并发写,如需并行,应先分片写临时文件,再合并
def write_jsonl(path, records):
with open(path, "w", encoding="utf-8") as f:
for obj in records:
s = json.dumps(obj, separators=(",", ":"))
f.write(s + "\n")
jsonlines 库值不值得引入?
jsonlines(pip install jsonlines)封装了读写逻辑,API 简洁:
立即学习“Python免费学习笔记(深入)”;
- 读:
jsonlines.open(f).iter()自动跳过空行、抛出带行号的异常 - 写:
jsonlines.open(f, "w").write_all(records)自动处理换行与编码
但它不是标准库,增加依赖;且底层仍是逐行 json.loads,性能无本质提升。小项目图省事可用,CI/嵌入式或强约束环境建议手写更可控。
真正容易被忽略的是:JSONL 文件没有 schema 约束,同一文件里不同行的字段可能不一致。如果后续要做 Pandas 分析,务必在读取后做 pd.json_normalize() 或字段对齐,否则 pd.read_json(..., lines=True) 可能静默丢列。


















