0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何将流解析技术应用于JSON处理

Linux爱好者 来源:CSDN技术社区 作者:Python开发者 2022-06-24 12:07 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

如果你需要在 Python 中处理一个大的 JSON 文件,会很容易出现耗尽内存的情况。即使原始数据大小小于内存容量,Python 也会进一步增加内存使用量。这意味着程序会在与磁盘交互时处理缓慢,或在内存不足时崩溃。

一种常见的解决方案是流解析,也就是惰性解析、迭代解析或分块处理。让我们看看如何将此技术应用于 JSON 处理。

问题:Python中加载JSON内存效率低

我们使用这个大小为24MB的JSON文件来举例,它在加载时会对内存产生明显的影响。这个JSON对象是在GitHub中,用户对存储库执行操作时的事件列表:

[{"id":"2489651045","type":"CreateEvent","actor":
{"id":665991,"login":"petroav","gravatar_id":"","url":"https://api.github.com/users/petroav","avatar_url":"https://avatars.githubusercontent.com/u/665991?"},"repo":
{"id":28688495,"name":"petroav/6.828","url":"https://api.github.com/repos/petroav/6.828"},"payload":
{"ref":"master","ref_type":"branch","master_branch":"master","description":"SolutiontohomeworkandassignmentsfromMIT's6.828(OperatingSystemsEngineering).Doneinmysparetime.","pusher_type":"user"},"public":true,"created_at":"2015-01-01T1500Z"},
...
]

我们的目标是找出给定用户在与哪些存储库进行交互。下面是一个简单的 Python 程序:

importjson

withopen("large-file.json","r")asf:
data=json.load(f)

user_to_repos={}
forrecordindata:
user=record["actor"]["login"]
repo=record["repo"]["name"]
ifusernotinuser_to_repos:
user_to_repos[user]=set()
user_to_repos[user].add(repo)

输出结果是一个用户名映射到存储库名称的字典。我们使用 Fil 内存分析器运行它时,可以发现内存使用的峰值达到了124MB,还可以发现两个主要的内存分配来源:

  1. 读取文件
  2. 将生成的字节解码为 Unicode 字符串

9e32edfc-f371-11ec-ba43-dac502259ad0.png

但我们加载的原始文件是24MB。一旦我们将它加载到内存中并将其解码为文本 (Unicode)Python 字符串,它需要的空间远远超过 24MB。这是为什么?

扩展知识:Python字符串的内存表示

Python字符串在表示时会被更少使用内存的方法优化。每个字符串都有固定的开销,如果字符串可以表示为 ASCII,则每个字符只使用一个字节的内存。如果字符串使用更多扩展字符,则每个字符可能使用4个字节。我们可以使用 sys.getsizeof() 查看一个对象需要多少内存:

>>>importsys
>>>s="a"*1000
>>>len(s)
1000
>>>sys.getsizeof(s)
1049

>>>s2=""+"a"*999
>>>len(s2)
1000
>>>sys.getsizeof(s2)
2074

>>>s3=""+"a"*999
>>>len(s3)
1000
>>>sys.getsizeof(s3)
4076

在上面的例子中3个字符串都是 1000 个字符长,但它们使用的内存量取决于它们包含的字符。

在本例中我们的大JSON 文件里包含不适合ASCII编码的字符,正是因为它是作为一个巨大的字符串加载的,所以整个巨大的字符串会使用效率较低的内存表示。

流处理解决方案

很明显,将整个JSON文件直接加载到内存中是一种内存浪费。

对一个结构为对象列表的 JSON 文件,理论上我们可以一次解析一个块,而不是一次全部解析,以此来减少内存的使用量。目前有许多 Python 库支持这种 JSON 解析方式,下面我们使用 ijson 库来举例。

importijson

user_to_repos={}

withopen("large-file.json","r")asf:
forrecordinijson.items(f,"item"):
user=record["actor"]["login"]
repo=record["repo"]["name"]
ifusernotinuser_to_repos:
user_to_repos[user]=set()
user_to_repos[user].add(repo)

如果使用json标准库,数据一旦被加载文件就会被关闭。而使用ijson,文件必须保持打开状态,因为当我们遍历记录时,JSON 解析器正在按需读取文件。有关更多详细信息,请参阅 ijson 文档。

在内存分析器运行它时,可以发现内存使用的峰值降到了3.6MB,问题解决了!而且在此例子中,使用 ijson 的流式处理也会提升运行时的性能,当然这个性能取决于数据集或算法

9e41e712-f371-11ec-ba43-dac502259ad0.png

其他解决方法

  • Pandas:Pandas 具有读取 JSON 的能力,理论上它可以以更节省内存的方式读取。
  • SQLite:SQLite 数据库可以解析 JSON,将 JSON 存储在列中,以及查询 JSON数据。因此,可以将 JSON 加载到磁盘支持的数据库文件中,并对它运行查询来提取相关的数据子集。

最后,如果可以控制输出格式,则可以通过切换到更高效的表示来减少 JSON 处理的内存使用量。例如,从单个巨大的 JSON 对象列表切换到每行一条 JSON 记录,这意味着每条解码的 JSON 记录将只使用少量内存。

知识延伸

前段时间,Python开发者公号推荐了一款很实用的 JSON 工具,可以更轻松直观地查看 JSON。

原文标题:Python 处理超大 JSON 文件,这个方法简单!

文章出处:【微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    9

    文章

    3173

    浏览量

    76119
  • python
    +关注

    关注

    57

    文章

    4858

    浏览量

    89592
  • JSON
    +关注

    关注

    0

    文章

    125

    浏览量

    7704

原文标题:Python 处理超大 JSON 文件,这个方法简单!

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    远心镜头核心技术解析与应用

    远心镜头(TelecentricLens)是一种专为精密光学成像设计的镜头系统,其核心在于消除传统镜头中常见的透视失真和放大倍率变化问题。该技术广泛应用于工业检测、计量测量和机器视觉等领域,通过确保
    的头像 发表于 12-08 17:25 114次阅读
    远心镜头核心<b class='flag-5'>技术</b><b class='flag-5'>解析</b>与应用

    解析淘宝拍立淘按图搜索API接口与JSON数据示例参考

    应用。 获取API权限和密钥(App Key、App Secret)。 使用Python调用API的示例代码。 3. JSON数据示例与解析 返回的JSON数据结构解析。 如何提取关键
    的头像 发表于 11-11 13:19 119次阅读

    深度解析淘宝拍立淘按图搜索API接口与JSON数据示例参考

    引言 淘宝拍立淘是淘宝推出的一项基于图像识别的搜索功能,用户可以通过上传图片来搜索相似商品。淘宝开放平台提供了拍立淘按图搜索API接口,帮助开发者实现图像搜索功能。本文深度解析淘宝拍立淘按图搜索
    的头像 发表于 11-06 13:43 96次阅读

    FAQ_MA35_Family eMMC如何将映像编程到其中一个分区中,并将其他分区用于其他目的?

    FAQ_MA35_Family eMMC如何将映像编程到其中一个分区中,并将其他分区用于其他目的?
    发表于 09-02 08:05

    如何将GCC项目导入NuEclipse?

    如何将GCC项目导入NuEclipse?
    发表于 09-01 07:04

    什么是反时限过保护?深入解析反时限过保护的应用场景与优势

    在电力系统中,过保护是保障设备安全运行和电网稳定性的重要环节。其中,反时限过保护以其独特的动作特性,在特定应用场景下发挥着不可替代的作用。本文深入探讨反时限过保护的原理、优势,
    的头像 发表于 07-17 13:53 2146次阅读
    什么是反时限过<b class='flag-5'>流</b>保护?深入<b class='flag-5'>解析</b>反时限过<b class='flag-5'>流</b>保护的应用场景与优势

    技术分享 | 迅为RK3568开发板如何将 Linux 板卡虚拟成U盘

    技术分享 | 迅为RK3568开发板如何将 Linux 板卡虚拟成U盘
    的头像 发表于 06-04 10:57 886次阅读
    <b class='flag-5'>技术</b>分享 | 迅为RK3568开发板<b class='flag-5'>如何将</b> Linux 板卡虚拟成U盘

    如何将一个FA模型开发的声明式范式应用切换到Stage模型

    模型切换概述 本文介绍如何将一个FA模型开发的声明式范式应用切换到Stage模型,您需要完成如下动作: 工程切换:新建一个Stage模型的应用工程。 配置文件切换:config.json切换
    发表于 06-04 06:22

    不用联网不用编程,PLC通过智能网关快速实现HTTP协议JSON格式与MES等系统平台双向数据通讯

    进行解析数据写入到PLC,实现PLC与HTTP服务端双向通讯;作为服务端时根据客户端URL中的路径查找所配置的数据,打包成JSON文件后返回给客户端。
    的头像 发表于 05-13 14:40 872次阅读
    不用联网不用编程,PLC通过智能网关快速实现HTTP协议<b class='flag-5'>JSON</b>格式与MES等系统平台双向数据通讯

    如何将Linux安装包快速转成玲珑包

    本篇将以 motrix 为例为大家展示如何将 Linux 安装包快速转成玲珑包。
    的头像 发表于 03-12 16:01 1260次阅读
    <b class='flag-5'>如何将</b>Linux安装包快速转成玲珑包

    如何将项目从IAR迁移到Embedded Studio

    本文描述如何将IAR EWARM项目迁移到SEGGER Embedded Studio(简称SES)中。
    的头像 发表于 02-25 17:11 1069次阅读
    <b class='flag-5'>如何将</b>项目从IAR迁移到Embedded Studio

    k230如何将yolo分类视频推理后的视频结果保存到本地?

    请问k230如何将yolo分类视频推理后的视频结果保存到本地?
    发表于 02-08 08:09

    如何将ADS1278通过SPI与处理器连接?

    在设计电路时,由于采用ADS1278进行8通道同步采样,通过SPI接口与ARM微处理器的SPI接口进行连接,而ADS1278工作在Discrete模式下,请问专家如何将ADS1278通过SPI与处理器连接?此时DOUT1-8如
    发表于 02-07 07:31

    AN3408-如何将12位ADC用于力敏电阻

    电子发烧友网站提供《AN3408-如何将12位ADC用于力敏电阻.pdf》资料免费下载
    发表于 01-21 14:38 0次下载
    AN3408-<b class='flag-5'>如何将</b>12位ADC<b class='flag-5'>用于</b>力敏电阻

    ±15V精密单刀双掷模拟开关应用于二次谐波信号处理

    ±15V精密单刀双掷模拟开关应用于二次谐波信号处理
    的头像 发表于 01-17 15:46 646次阅读
    ±15V精密单刀双掷模拟开关<b class='flag-5'>应用于</b>二次谐波信号<b class='flag-5'>处理</b>