pin_drop当前位置:知识文库 ❯ 图文
Python json.dump详解 - 文件写入与流式序列化技巧
一、概述
json.dump() 是 json 模块中将 Python 对象序列化为 JSON 格式并直接写入文件对象的函数。与 dumps() 不同,dump() 直接将结果写入文件流,无需在内存中生成完整的 JSON 字符串,因此在处理大型数据时更节省内存。dump() 的参数与 dumps() 基本一致,额外接受一个文件对象参数。
二、语法
代码示例
import json
json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True,
check_circular=True, allow_nan=True,
cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw)三、参数说明
四、返回值
返回 None。JSON 数据直接写入文件对象,不返回字符串。
五、代码示例
示例1:基本文件写入
代码示例
import json
data = {
"users": [
{"id": 1, "name": "张三", "role": "admin"},
{"id": 2, "name": "李四", "role": "user"},
],
"total": 2,
"updated": "2024-01-15",
}
# 写入JSON文件
with open("users.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print("已写入 users.json")
# 读取验证
with open("users.json", "r", encoding="utf-8") as f:
content = f.read()
print(content)输出:
代码示例
已写入 users.json
{
"users": [
{
"id": 1,
"name": "张三",
"role": "admin"
},
{
"id": 2,
"name": "李四",
"role": "user"
}
],
"total": 2,
"updated": "2024-01-15"
}示例2:大数据流式写入
代码示例
import json
def generate_large_data(count):
"""生成大量数据"""
for i in range(count):
yield {"id": i, "value": f"item_{i}", "score": i * 0.5}
# 方式1:一次性写入(占用内存大)
data_list = list(generate_large_data(5))
with open("data_batch.json", "w", encoding="utf-8") as f:
json.dump(data_list, f, ensure_ascii=False, indent=2)
print("批量写入完成")
# 方式2:手动流式写入(节省内存)
with open("data_stream.json", "w", encoding="utf-8") as f:
f.write("[\n")
first = True
for item in generate_large_data(5):
if not first:
f.write(",\n")
json.dump(item, f, ensure_ascii=False, indent=2)
first = False
f.write("\n]")
print("流式写入完成")输出:
代码示例
批量写入完成
流式写入完成示例3:配置文件管理器
代码示例
import json
import os
class ConfigManager:
"""JSON配置文件管理器"""
def __init__(self, filepath):
self.filepath = filepath
self.config = {}
if os.path.exists(filepath):
self.load()
def load(self):
"""从文件加载配置"""
with open(self.filepath, "r", encoding="utf-8") as f:
self.config = json.load(f)
def save(self):
"""保存配置到文件"""
with open(self.filepath, "w", encoding="utf-8") as f:
json.dump(self.config, f, ensure_ascii=False, indent=2)
def get(self, key, default=None):
return self.config.get(key, default)
def set(self, key, value):
self.config[key] = value
self.save()
def delete(self, key):
if key in self.config:
del self.config[key]
self.save()
def display(self):
print(f"配置文件: {self.filepath}")
for key, value in self.config.items():
print(f" {key}: {value}")
# 使用示例
config = ConfigManager("app_config.json")
config.set("app_name", "我的应用")
config.set("version", "1.0.0")
config.set("debug", True)
config.set("max_connections", 100)
config.display()输出:
代码示例
配置文件: app_config.json
app_name: 我的应用
version: 1.0.0
debug: True
max_connections: 100六、实际应用场景
-
数据持久化:将程序运行状态、用户数据保存到 JSON 文件
-
配置文件管理:读写 JSON 格式的应用配置
-
大数据导出:将数据库查询结果导出为 JSON 文件
七、注意事项
注意1:
json.dump()的文件对象必须支持write()方法,且应以文本模式打开("w"),并指定encoding="utf-8"。
注意2:
dump()直接写入文件流,不会返回 JSON 字符串。如果需要同时获取字符串和写入文件,应使用dumps()。
注意3:写入文件时应始终使用
with语句,确保文件正确关闭。
注意4:对于超大文件,
dump()仍需在内存中构建完整的 Python 对象。真正的流式处理需要手动控制写入过程。
提示:
json.dump()比f.write(json.dumps())更高效,因为前者直接写入文件流,避免了中间字符串的内存分配。
八、相关方法对比
九、小结
-
json.dump()将 Python 对象直接序列化写入文件,比dumps()+write()更高效 -
参数与
dumps()一致,额外需要文件对象参数 -
处理中文时需设置
ensure_ascii=False,美化输出使用indent -
大数据场景可手动实现流式写入,避免一次性加载全部数据到内存
十、练习题
练习1
编写一个函数 export_to_json(data, filepath),将数据导出为 JSON 文件,自动创建不存在的目录。
练习2
编写一个函数,将列表数据分批写入 JSON 文件,每批1000条,使用手动流式写入方式。
练习3
编写一个函数,比较 json.dump() 和 f.write(json.dumps()) 在写入大文件时的内存占用差异。
小贴士
json.dump() 的 fp 参数不仅可以是文件对象,也可以是任何实现了 write() 方法的对象,例如 io.StringIO、网络 socket 流、HTTP 响应流等。这使得 dump() 非常灵活,可以适应各种输出目标,而不局限于本地文件。
常见问题
json.dump() 和 json.dumps() 应该选哪个?
如果目标是将 JSON 写入文件,优先使用 dump(),它更节省内存;如果需要将 JSON 作为字符串用于网络传输、API 响应或进一步处理,使用 dumps()。
为什么写入文件时要指定 encoding="utf-8"?
不同操作系统默认编码可能不同(Windows 默认 GBK)。显式指定 utf-8 可以确保中文等非 ASCII 字符正确写入文件,避免跨平台编码问题。
如何实现真正的流式 JSON 写入?
json.dump() 本身不支持流式写入生成器。真正的流式写入需要手动控制:先写 [,然后逐个 dump 每个元素并手动添加逗号分隔,最后写 ]。或者使用第三方库如 ijson 来实现。
json.dump() 比 f.write(json.dumps()) 快多少?
对于小数据差异不明显。对于大数据(MB级别),dump() 避免了中间完整字符串的内存分配,可以减少约 50% 的内存峰值。速度方面两者接近,dump() 略优,因为少了一次字符串拼接操作。
本文涉及AI创作
内容由AI创作,请仔细甄别