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

    文章

    2756

    浏览量

    72672
  • python
    +关注

    关注

    51

    文章

    4666

    浏览量

    83433
  • JSON
    +关注

    关注

    0

    文章

    111

    浏览量

    6811

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

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

收藏 人收藏

    评论

    相关推荐

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

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

    如何将大数据技术应用于精益六西格玛?

    在当今信息爆炸的时代,大数据技术的应用不仅在工商企业中变得日趋普遍,而且在各个领域都展现出了强大的潜力。其中,将大数据技术应用于精益六西格玛,不仅可以提升效率,还可以改善质量。本文将介绍如何将
    的头像 发表于 12-18 09:58 276次阅读

    关于JSON数据库

    如何理解JSON数据库?作为NoSQL数据库的一种类型,JSON数据库有哪些优势呢?JSON数据库如何运作,它为应用程序开发者带来了哪些价值呢?
    的头像 发表于 12-06 13:46 394次阅读
    关于<b class='flag-5'>JSON</b>数据库

    什么是JSON数据库

    如何理解JSON数据库?作为NoSQL数据库的一种类型,JSON数据库有哪些优势呢?JSON数据库如何运作,它为应用程序开发者带来了哪些价值呢?文章速览:什么是JSON什么是
    的头像 发表于 12-02 08:04 346次阅读
    什么是<b class='flag-5'>JSON</b>数据库

    如何将AD5750接地?

    目前我正在利用AD5750-1做一个项目——“用于PLC和DCS应用的灵活、中级性能、电压和电流输出电路”。 我想询问如何将AD5750接地。AD5750有两个GND引脚,引脚5靠近DVCC,引脚
    发表于 11-27 08:25

    如何利用Python和pandas来处理json数据

    了如何利用Python和pandas(Python的第三方库)来处理json数据,主要内容包含: json数据简介 常用json数据转化网站 jso
    的头像 发表于 11-01 10:59 567次阅读
    如何利用Python和pandas来<b class='flag-5'>处理</b><b class='flag-5'>json</b>数据

    C语言怎样处理json文件?

    获取到的JSON文件,怎样通过C语言进行处理,因为单片机里面只能用C语言,有没有C语言处理起来比较方便的操作
    发表于 11-01 06:16

    一个应用于单片机的按键处理模块!

    一个应用于单片机的按键处理模块!
    的头像 发表于 10-24 16:28 318次阅读
    一个<b class='flag-5'>应用于</b>单片机的按键<b class='flag-5'>处理</b>模块!

    如何用C语言进行json的序列化和反序列化

    列化呢? 当前,应用最广泛的C语言json解析库当属cJSON,但是,使用cJSON读json进行序列化和反序列化,需要根据key一个一个进行处理,会导致代码冗余,逻辑性不强,哪有没有
    的头像 发表于 10-07 11:05 811次阅读

    更低内存占用的通用Json库-RyanJson

    RyanJson是一个小巧的c语言json解析器,包含json文本文件解析 / 生成,专门针对内存占用进行优化,相比cJSON内存占用减少30% - 60%,运行速度和cJSON差不多
    的头像 发表于 08-24 17:23 782次阅读
    更低内存占用的通用<b class='flag-5'>Json</b>库-RyanJson

    支持的JSON数据选项介绍

    GPU 加速的 RAPID JSON 数据处理
    的头像 发表于 07-05 16:30 255次阅读

    求助,有人知道NONOS JSON代码示例吗?

    任何人都有一些他们愿意分享的示例 JSON 解析代码?请使用 NONOS jsonparse_setup() 等库。
    发表于 06-12 07:52

    如何从网络服务器读取连续的JSON数据

    我有一个家庭自动化系统,它在网页上以 JSON 格式为十几个测量参数提供连续的数据(每秒)。 我需要阅读它们并复制相应的变量。 所以全局三个步骤: 1. 登录到服务器(摘要式身份验证)-我认为已
    发表于 06-05 08:19

    为什么无法解析HTML/Json

    无法解析HTML/Json
    发表于 06-05 06:03

    网络工程师学Python之JSON数据交换格式解析

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于JavaScript语法,但也可以被其他语言如Python解析和生成。
    的头像 发表于 04-21 16:53 1187次阅读