<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
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

    文章

    2790

    瀏覽量

    72964
  • python
    +關注

    關注

    52

    文章

    4698

    瀏覽量

    83610
  • JSON
    +關注

    關注

    0

    文章

    112

    瀏覽量

    6843

原文標題:Python 處理超大 JSON 文件,這個方法簡單!

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    ?PLC設備通過智能網關采用HTTP協議JSON文件對接MES、ERP等系統平臺

    給HTTP的服務端, 如果服務端有返回的JSON,網關進行解析數據寫入到PLC,實現PLC與HTTP服務端雙向通訊;作為服務端時根據客戶端URL中的路徑查找所配置的數據,打包成JSON
    發表于 05-13 12:04

    ?PLC從HTTP服務端獲取JSON文件,解析數據到寄存器

    文件提交給HTTP的服務端; 服務端有返回的JSON,或者GET命令獲取到的JSON,網關進行解析數據寫入到PLC寄存器。 本文主要描述通過GET命令獲取數據,
    發表于 01-24 09:47

    如何將大數據技術應用于精益六西格瑪?

    在當今信息爆炸的時代,大數據技術的應用不僅在工商企業中變得日趨普遍,而且在各個領域都展現出了強大的潛力。其中,將大數據技術應用于精益六西格瑪,不僅可以提升效率,還可以改善質量。本文將介紹如何將
    的頭像 發表于 12-18 09:58 ?363次閱讀

    關于JSON數據庫

    如何理解JSON數據庫?作為NoSQL數據庫的一種類型,JSON數據庫有哪些優勢呢?JSON數據庫如何運作,它為應用程序開發者帶來了哪些價值呢?
    的頭像 發表于 12-06 13:46 ?545次閱讀
    關于<b class='flag-5'>JSON</b>數據庫

    什么是JSON數據庫

    如何理解JSON數據庫?作為NoSQL數據庫的一種類型,JSON數據庫有哪些優勢呢?JSON數據庫如何運作,它為應用程序開發者帶來了哪些價值呢?文章速覽:什么是JSON什么是
    的頭像 發表于 12-02 08:04 ?472次閱讀
    什么是<b class='flag-5'>JSON</b>數據庫

    如何將AD5750接地?

    目前我正在利用AD5750-1做一個項目——“用于PLC和DCS應用的靈活、中級性能、電壓和電流輸出電路”。 我想詢問如何將AD5750接地。AD5750有兩個GND引腳,引腳5靠近DVCC,引腳
    發表于 11-27 08:25

    如何正確的8009應用于反相放大電路中?

    左右(正相飽和),但是我使用multisim仿真是沒有問題的,請問應如何正確的8009應用于反相放大電路中?如果不能用于反相放大電路請問如何通過手冊鑒別?其中的機理是什么? 仿真輸出波形 通道A
    發表于 11-21 07:07

    如何利用Python和pandas來處理json數據

    了如何利用Python和pandas(Python的第三方庫)來處理json數據,主要內容包含: json數據簡介 常用json數據轉化網站 jso
    的頭像 發表于 11-01 10:59 ?862次閱讀
    如何利用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 ?429次閱讀
    一個<b class='flag-5'>應用于</b>單片機的按鍵<b class='flag-5'>處理</b>模塊!

    如何用C語言進行json的序列化和反序列化

    列化呢? 當前,應用最廣泛的C語言json解析庫當屬cJSON,但是,使用cJSON讀json進行序列化和反序列化,需要根據key一個一個進行處理,會導致代碼冗余,邏輯性不強,哪有沒有
    的頭像 發表于 10-07 11:05 ?908次閱讀

    什么是ICM 如何將ICM用于加密

    電子發燒友網站提供《什么是ICM 如何將ICM用于加密.pdf》資料免費下載
    發表于 09-25 11:03 ?0次下載
    什么是ICM <b class='flag-5'>如何將</b>ICM<b class='flag-5'>用于</b>加密

    更低內存占用的通用Json庫-RyanJson

    RyanJson是一個小巧的c語言json解析器,包含json文本文件解析 / 生成,專門針對內存占用進行優化,相比cJSON內存占用減少30% - 60%,運行速度和cJSON差不多
    的頭像 發表于 08-24 17:23 ?920次閱讀
    更低內存占用的通用<b class='flag-5'>Json</b>庫-RyanJson

    支持的JSON數據選項介紹

    GPU 加速的 RAPID JSON 數據處理
    的頭像 發表于 07-05 16:30 ?294次閱讀

    求助,有人知道NONOS JSON代碼示例嗎?

    任何人都有一些他們愿意分享的示例 JSON 解析代碼?請使用 NONOS jsonparse_setup() 等庫。
    發表于 06-12 07:52
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>