不能直接用json.dump()写多行json,因其生成单个嵌套json结构,而jsonl要求每行一个独立、合法json对象,无逗号分隔、不包数组;必须用json.dumps()+换行逐行写入。

为什么不能直接用 json.dump() 写多行JSON?
因为 json.dump() 默认输出一个完整、格式化(或紧凑)的 JSON 对象/数组,它会把所有数据塞进单个结构里。而“多行 JSON”(也叫 JSON Lines 或 NDJSON)要求每行一个独立、合法的 JSON 值(如 {"id": 1}、[1,2,3]),中间**不能有逗号分隔,也不能包在数组里**。直接用 json.dump() 写一堆对象,结果要么是语法错误,要么是嵌套结构,下游工具(如 jq、Spark、Logstash)根本没法按行解析。
用 json.dumps() + 每行单独写入最可靠
核心思路:不依赖文件级序列化,而是对每个 Python 对象调用 json.dumps() 得到字符串,再加换行写入。这样完全可控,且天然支持流式——来一个写一个,内存不累积。
实操建议:
- 始终显式指定
ensure_ascii=False,否则中文变\u4f60; - 避免用
indent=2—— 它会破坏单行结构,让输出变成多行缩进,不再是 valid JSON Lines; - 用
open(..., 'a', encoding='utf-8')追加模式,适合长时间运行的日志类写入; - 若需原子性(比如防止进程崩溃时写半行),可先写临时文件,再
os.replace()覆盖原文件。
示例:
import json
data_list = [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]
with open("output.jsonl", "w", encoding="utf-8") as f:
for obj in data_list:
f.write(json.dumps(obj, ensure_ascii=False) + "\n")
写入时遇到 UnicodeEncodeError: 'charmap' codec can't encode character 怎么办?
这是 Windows 默认控制台/文件编码(cp1252)无法处理 UTF-8 字符(如 emoji、中文、特殊符号)导致的。关键不是 JSON 本身,而是文件打开时没指定编码。
必须显式传 encoding='utf-8' 给 open() —— 即使你用的是 Python 3.7+,这个参数也不能省。Windows 上尤其容易踩坑,Mac/Linux 默认行为稍友好但也不保证。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
错误写法:open("out.jsonl", "w") → 可能崩;
正确写法:open("out.jsonl", "w", encoding="utf-8") → 稳定。
需要压缩写入(如直接写 .jsonl.gz)怎么办?
别先写明文再调 gzip 命令——效率低、占磁盘、不原子。直接用 gzip.open() 替代 open(),其余逻辑完全不变。
注意点:
-
gzip.open(..., "wt", encoding="utf-8")中的"wt"表示文本写入(自动编码),不能用"wb"否则write()会拒收字符串; -
json.dumps()返回str,和"wt"模式匹配; - 压缩比取决于数据重复度,JSON Lines 本身压缩率通常不错。
示例:
import gzip
import json
with gzip.open("output.jsonl.gz", "wt", encoding="utf-8") as f:
for obj in [{"ts": 1712345678, "event": "login"}]:
f.write(json.dumps(obj, ensure_ascii=False) + "\n")
真正容易被忽略的是:JSON Lines 的“行”必须是完整、可独立解析的 JSON 值,任何一行里出现未闭合引号、多余逗号或控制字符(如裸 \x00),整行就失效。写入前最好用 try/except json.JSONDecodeError 做轻量校验,尤其是当数据来自不可信源时。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










