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爱好者】欢迎添加关注!文章转载请注明出处。

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

    关注

    8

    文章

    3017

    浏览量

    73996
  • python
    +关注

    关注

    56

    文章

    4792

    浏览量

    84617
  • JSON
    +关注

    关注

    0

    文章

    117

    浏览量

    6963

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

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

收藏 人收藏

    评论

    相关推荐

    如何将FMEA应用于PCB设计第一阶段?

    的每一个环节都充满了挑战和不确定性,稍有不慎就可能引发故障。 为了应对这些挑战,FMEA(Failure Modes and Effects Analysis,即故障模式与效应分析)应用于PCB设计的第一阶段显得尤为重要。FMEA是一种系统化的预防策略,旨在识别和评估产
    的头像 发表于 12-03 11:19 162次阅读

    实例篇 4G模组软件之json数据处理

    今天我会把4G模组软件的json数据处理整理成文,以低功耗模组Air780E为例,一一展示出来:
    的头像 发表于 11-12 12:17 186次阅读

    控阵列芯片和普通芯片的区别

    控阵列芯片与普通芯片在设计与应用上存在显著差异 设计原理:微控阵列芯片以微米级通道操控流体,集成多种实验功能;普通芯片则通常基于晶体管,用于电子信号处理。 应用领域:微
    的头像 发表于 10-30 15:10 186次阅读

    Taro鸿蒙技术内幕系列(一):如何将React代码跑在ArkUI上

    基于 Taro 打造的京东鸿蒙 APP 已跟随鸿蒙 Next 系统公测,本系列文章深入解析 Taro 如何实现使用 React 开发高性能鸿蒙应用的技术内幕。
    的头像 发表于 10-25 17:24 292次阅读
    Taro鸿蒙<b class='flag-5'>技术</b>内幕系列(一):<b class='flag-5'>如何将</b>React代码跑在ArkUI上

    TI TSC应用于各种和多种功能

    电子发烧友网站提供《TI TSC应用于各种和多种功能.pdf》资料免费下载
    发表于 10-22 10:15 0次下载
    <b class='flag-5'>将</b>TI TSC<b class='flag-5'>应用于</b>各种和多种功能

    如何将LVDS/OLDI桥接到HDMI/DVI

    电子发烧友网站提供《如何将LVDS/OLDI桥接到HDMI/DVI.pdf》资料免费下载
    发表于 09-27 09:35 1次下载
    <b class='flag-5'>如何将</b>LVDS/OLDI桥接到HDMI/DVI

    JSON协议是什么,物联网中的RTU中如何使用JSON协议和服务器交互

    一 概述 1.1 什么是 JSON JSON是JavaScript Object Notation的简称,中文含义为“JavaScript 对象表示法”,它是一种数据交换的文本格式,而不是一种编程
    的头像 发表于 09-25 16:14 672次阅读
    <b class='flag-5'>JSON</b>协议是什么,物联网中的RTU中如何使用<b class='flag-5'>JSON</b>协议和服务器交互

    如何将 THVD8000 应用于星型网络系统

    电子发烧友网站提供《如何将 THVD8000 应用于星型网络系统.pdf》资料免费下载
    发表于 09-12 10:36 0次下载
    <b class='flag-5'>如何将</b> THVD8000 <b class='flag-5'>应用于</b>星型网络系统

    如何将BQ35100配置为EOS模式

    电子发烧友网站提供《如何将BQ35100配置为EOS模式.pdf》资料免费下载
    发表于 09-11 10:03 0次下载
    <b class='flag-5'>如何将</b>BQ35100配置为EOS模式

    如何将TRIZ应用于PCB设计的优化阶段?

    随着技术的不断进步和市场竞争的日益激烈,如何高效、创新地优化PCB设计,以降低成本、提升性能、缩短上市周期,成为了工程师们共同面临的挑战。TRIZ(Theory of Inventive
    的头像 发表于 09-04 16:40 336次阅读

    如何将精益思维应用于传统工厂的数字化转型?

    随着科技的不断进步和市场竞争的日益激烈,传统工厂正面临着前所未有的挑战。如何在这场数字化浪潮中站稳脚跟,甚至实现弯道超车?答案或许就在精益思维中。今天,深圳天行健企业管理咨询公司就来解析如何将精益
    的头像 发表于 07-18 09:43 217次阅读

    ZWS云平台应用(5)-raw数据解析

    设备透传上报的原始raw数据,如何解析成更易读JSON数据格式?传感器数据输出是二进制,这种方式的数据量小,传输速度快。但二进制数据不够直观,需要将数据解析成更易读的JSON数据格式。
    的头像 发表于 06-19 08:25 324次阅读
    ZWS云平台应用(5)-raw数据<b class='flag-5'>解析</b>

    PLC设备通过智能网关采用HTTP协议JSON文件对接MES、ERP等系统平台

    给HTTP的服务端, 如果服务端有返回的JSON,网关进行解析数据写入到PLC,实现PLC与HTTP服务端双向通讯;作为服务端时根据客户端URL中的路径查找所配置的数据,打包成JSON
    发表于 05-13 12:04

    ArkTS语言基础类库-解析

    支持,包括有理数的比较、获取分子分母等功能。 提供Scope接口用于描述一个字段的有效范围。 提供二进制数据处理的能力,常见于TCP或文件系统操作等场景中用于
    发表于 02-20 16:44

    PLC从HTTP服务端获取JSON文件,解析数据到寄存器

    文件提交给HTTP的服务端; 服务端有返回的JSON,或者GET命令获取到的JSON,网关进行解析数据写入到PLC寄存器。 本文主要描述通过GET命令获取数据,
    发表于 01-24 09:47