功能说明
read_jsonl 是一个生成器,按行读取 JSON Lines 文件,每次只把一个对象放进内存。空行会被跳过;单行字节数超过上限、JSON 语法错误或顶层不是对象时,都会抛出带行号的 JsonlError,便于定位坏数据。示例先写入四条记录,其中第三条故意缺少值,演示读取在第 3 行停止。
关键代码
for line_no, raw in enumerate(handle, start=1):
size = len(raw.encode("utf-8"))
if size > max_record_bytes:
raise JsonlError(line_no, f"record is {size} bytes, limit is {max_record_bytes}")
line = raw.strip()
if not line:
continue
record = json.loads(line)
...
yield record
raw.strip() 只影响判断与解析,行号来自 enumerate,两者不会互相干扰。
使用注意
- 大小限制按 UTF-8 字节数计算,而不是字符数,能真实反映内存占用。
- 生成器保持文件打开,调用方应尽快消费完或显式关闭;提前
break时由垃圾回收关闭文件。 - 只接受 JSON 对象,数组或标量会报错;如果数据允许其他顶层类型,需要放宽检查。
- 错误会立即终止迭代,已经产出的记录仍然有效;需要跳过坏行时可改成收集错误后继续。
- 该函数不做编码探测,文件必须是 UTF-8;其他编码应在打开前转换。
验证方式
运行脚本会先打印 1、2 两条记录,然后输出 stopped after 2 records: line 3: invalid JSON。把第三条改成合法对象可读到第 4 条;把 max_record_bytes 调小可验证超长记录分支。