Python JSON 解析详解:日志分析实战
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在日志记录、API 交互等场景中广泛使用。Python 标准库 json 提供了简洁的 API 用于 JSON 数据的解析(字符串转字典)和序列化(字典转字符串)。本文将以日志分析为例,详细介绍 Python 处理 JSON 数据的方法。
JSON 解析核心方法
Python 的 json 模块提供了两个核心函数用于 JSON 处理:
| 方法 | 功能 | 适用场景 |
|---|---|---|
json.loads(s) |
将 JSON 字符串 s 解析为 Python 字典 / 列表 |
处理内存中的 JSON 字符串(如日志行) |
json.dumps(obj) |
将 Python 字典 / 列表序列化为 JSON 字符串 | 将数据写入文件或通过网络传输 |
json.load(f) |
从文件对象 f 中读取 JSON 数据并解析 |
直接读取 JSON 文件 |
json.dump(obj, f) |
将 Python 对象序列化并写入文件 f |
直接写入 JSON 文件 |
日志分析实战:筛选慢请求
以分析 JSON 格式的请求日志为例,假设日志文件 req_resp.log 中每行是一个 JSON 对象,包含 timeSpent(请求耗时,单位 ms)等字段。我们需要筛选出耗时超过 150ms 的请求。
完整代码实现
1 | #!/usr/bin/python3 |
代码解析
(1)文件读取与逐行处理
- 使用
with open(...)上下文管理器打开文件,自动处理资源释放(无需手动close())。 enumerate(f, 1)用于获取行号(从 1 开始),便于定位错误。
(2)JSON 解析(json.loads)
line.strip()去除每行首尾的空白字符(如换行符\n),避免解析错误。json.loads(line)将 JSON 字符串转换为 Python 字典(dict),便于通过键名访问字段(如log_data["timeSpent"])。
(3)异常处理
json.JSONDecodeError:捕获 JSON 格式错误(如括号不匹配、逗号错误)。- 检查
timeSpent字段是否存在,避免KeyError。 - 用
isinstance(time_spent, (int, float))确保字段类型为数字,避免比较时的TypeError。
(4)筛选逻辑
- 仅当
timeSpent大于 150ms 时,打印该请求的详细信息。
进阶技巧
提取特定字段
若只需关注部分字段(如 url、timeSpent、status),可针对性提取,减少输出冗余:
1 | # 提取特定字段 |
- 使用
dict.get(key, default)避免因字段不存在导致的KeyError。
写入筛选结果到文件
将筛选出的慢请求写入新文件,便于后续分析:
1 | # 打开输出文件 |
json.dump(..., ensure_ascii=False)确保中文等非 ASCII 字符正常显示(而非 Unicode 编码)。
处理超大日志文件
对于 GB 级别的大日志,readlines() 会占用大量内存,建议逐行读取(如上述代码),或分块处理。
常见问题与解决方案
| 问题场景 | 解决方案 |
|---|---|
| JSON 字符串包含中文 | 解析 / 序列化时指定 encoding="utf-8",并在 json.dump 中加 ensure_ascii=False。 |
| 日志行格式不标准(非纯 JSON) | 先用字符串处理(如正则匹配)提取 JSON 部分,再解析。 |
| 嵌套 JSON 结构 | 通过多级键访问(如 log_data["request"]["headers"]["User-Agent"])。 |
| 字段类型不固定(如有时是字符串有时是数字) | 解析后先判断类型(isinstance()),再转换(如 int(time_spent_str))。 |
v1.3.10