How to Process Large JSON Files in Python With ijson
TL;DR · AI 摘要
How to Process Large JSON Files in Python With ijson - KDnuggets publ: 22-Oct, 2026 - Blog Top Posts About - Topics AI C...
核心要点
- 主题聚焦:How to Process Large JSON Files in Python With i
- 来源:KDnuggets,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
如何使用 ijson 在 Python 中处理大型 JSON 文件 - KDnuggets
publ: 2026年10月22日
- 博客热门文章
- 主题 人工智能 职业建议 计算机视觉 数据工程 数据科学 语言模型 机器学习 MLOps NLP 编程 Python SQL
- 数据集
- 活动
- 资源 快速参考指南 推荐 技术简报
- 广告
订阅简报
#header end
/ad_wrapper
如何使用 ijson 在 Python 中处理大型 JSON 文件
我在 Python 中加载了一个大型 JSON 文件,发现内存使用量从 43 MB 激增到 808 MB。这里将解释发生了什么,以及流式处理如何彻底改变这一切。
By
Kanwal Mehreen
,KDnuggets 技术编辑兼内容专家,2026年10月22日发布于
人工智能
<div class="addthis_native_toolbox"></div>
JSON 是 Python 应用程序中存储和交换数据最常用的格式之一。对于小文件,Python 内置的 json 模块工作效果很好:
import json
with open("data.json") as f:
data = json.load(f)当文件变得很大时就会出现问题。
json.load() 会解析整个 JSON 文档,并在开始处理数据之前在内存中创建对应的 Python 对象。因此,一个在磁盘上仅占用几百兆字节的文件,在转换为 Python 字典、列表、字符串和数字后,可能需要消耗大量内存。
对于这种类型的工作负载,更好的选择是 ijson ,这是一个迭代式 JSON 解析器,允许您逐步处理数据。在本教程中,我们将使用包含旧金山土地地块数据的大型 JSON 文件。我们首先使用 json.load() 处理它,测量内存变化,然后使用 ijson 解决相同任务。
第一步:下载大型 JSON 数据集
为了这次实验,我们将使用旧金山城市地块数据集。我在这篇文章中使用 Google Colab。使用以下命令下载:
curl -L
https://raw.githubusercontent.com/zemirco/sf-city-lots-json/master/citylots.json
-o citylots.json可以使用以下命令检查其大小:
ls -lh citylots.json该数据集大小为 181 MB,足够大以展示加载和流式处理 JSON 之间的差异。文件遵循标准的 GeoJSON FeatureCollection 结构。可以使用以下代码检查:
import json
with open("citylots.json", "r") as f:
data = json.load(f)
print(data.keys())
data["features"][0]输出:
dict_keys(['type', 'features'])
{'type': 'Feature',
'properties': {'MAPBLKLOT': '0001001',
'BLKLOT': '0001001',
'BLOCK_NUM': '0001',
'LOT_NUM': '001',
'FROM_ST': '0',
'TO_ST': '0',
'STREET': 'UNKNOWN',
'ST_TYPE': None,
'ODD_EVEN': 'E'},
'geometry': {'type': 'Polygon',
'coordinates': [[[-122.42200352825247, 37.80848009696725, 0.0],
[-122.42207601332528, 37.808835019815085, 0.0],
[-122.42110217434863, 37.808803534992904, 0.0],
[-122.42106256906727, 37.80860105681815, 0.0],
[-122.42200352825247, 37.80848009696725, 0.0]]]}}对我们来说,重要的部分是 features 数组。
每个 feature 代表一个地块,包含两个主要部分:
feature
├── properties
│ ├── BLKLOT
│ ├── BLOCK_NUM
│ ├── LOT_NUM
│ └── STREET
│
└── geometry
└── coordinates我们的分析只需要 properties 下的几个值。然而,如果我们使用标准 JSON 解析器,Python 仍然必须加载所有 geometry 坐标。
第二步:使用 json.load() 处理文件
让我们先使用大多数 Python 开发者会自然尝试的方法。创建一个名为 standard_json.py 的文件:
import json
import time
start = time.perf_counter()
with open("citylots.json", "r") as f:
data = json.load(f)
features = data["features"]
market_count = 0
first_five = []
for feature in features:
properties = feature["properties"]
if properties.get("STREET") == "MARKET":
market_count += 1
if len(first_five) < 5:
first_five.append(
properties.get("BLKLOT")
)
elapsed = time.perf_counter() - start
print(f"Total parcels: {len(features):,}")
print(f"Market Street parcels: {market_count:,}")
print(f"First five parcel IDs: {first_five}")
print(f"Time: {elapsed:.2f} seconds")这段代码简单且完全有效。
问题出在这行代码:
data = json.load(f)在我们的循环可以处理任何一块数据之前,Python 必须:
读取整个文件
↓
解析每个 JSON 对象
↓
创建所有 Python 字典
↓
创建所有列表和坐标
↓
将所有内容存储在内存中
↓
开始分析这意味着即使我们只需要 STREET 和 BLKLOT 字段,也会加载数据集中的所有多边形和坐标。这是我得到的输出结果:
Total parcels: 206,560
Market Street parcels: 808
First five parcel IDs: ['0265003', '0265004', '0265005', '0290012', '0291001']
Time: 4.01 seconds第三步:测量内存使用情况
与其简单地说 json.load() 消耗大量内存,不如直接进行测量。
一个简单的选择是使用 memory-profiler 库。
安装方法:
pip install memory-profiler现在将代码替换为以下内容:
from memory_profiler import profile
import json
@profile
def process_file():
with open("citylots.json", "r") as f:
data = json.load(f)
features = data["features"]
market_count = 0
for feature in features:
if (
feature["properties"]
.get("STREET") == "MARKET"
):
market_count += 1
process_file()运行命令:
python -m memory_profiler standard_json.py需要重点关注的行是 data = json.load(f) :
行号 内存使用量 增量 出现次数 代码行内容
=============================================================
5 43.4 MiB 43.4 MiB 1 @profile
6 def process_file():
7
8 808.9 MiB 0.0 MiB 2 with open("citylots.json", "r") as f:
9 808.9 MiB 765.5 MiB 1 data = json.load(f)
10
11 808.9 MiB 0.0 MiB 1 features = data["features"]
12
13 808.9 MiB 0.0 MiB 1 market_count = 0
14
15 808.9 MiB 0.0 MiB 206561 for feature in features:
16
17 if (
18 808.9 MiB 0.0 MiB 413120 feature["properties"]
19 808.9 MiB 0.0 MiB 206560 .get("STREET") == "MARKET"
20 ):
21 808.9 MiB 0.0 MiB 808 market_count += 1
22
23 808.9 MiB 0.0 MiB 1 print("Total parcels:", len(features))
24 808.9 MiB 0.0 MiB 1 print("Market Street parcels:", market_count)此时可以明显看到内存消耗的显著增加。
为什么内存使用量可能远大于原始 JSON 文件?
因为像这样的 JSON:
{
"STREET": "MARKET"
}在解析后会变成多个 Python 对象:
字典
↓
Python 字符串键
↓
Python 字符串值嵌套的几何数组和数值坐标也会发生同样的情况。
因此,文件在磁盘上的大小与解析后的内存占用是不一致的。
这为我们提供了与 ijson 对比的基准。
第 4 步:使用 ijson 流式处理 JSON 文件
现在让我们在不加载完整文档的情况下解决同样的问题。
安装 ijson:
pip install ijson我们将使用的关键函数是:
ijson.items()我们的数据集具有以下层次结构:
root
│
├── type
│
└── features
├── item
├── item
├── item
└── ...因此,我们可以要求 ijson 逐个返回每个 feature:
import ijson
with open("citylots.json", "rb") as f:
for feature in ijson.items(
f,
"features.item"
):
print(feature)
break前缀:
features.item表示:
进入 features 数组并返回其中的每个元素。
ijson 不会创建一个巨大的 parcels 列表,而是逐个提供记录。
概念上:
Feature 1
↓
处理
↓
丢弃
Feature 2
↓
处理
↓
丢弃
Feature 3
↓
处理
↓
丢弃这会显著改变内存需求。
第 5 步:使用 ijson 执行相同分析
现在让我们重复执行完全相同的任务。
创建 stream_json.py:
import ijson import time
start = time.perf_counter()
total = 0 market_count = 0 first_five = []
with open("citylots.json", "rb") as f:
for feature in ijson.items( f, "features.item" ):
total += 1
properties = feature["properties"]
if properties.get("STREET") == "MARKET":
market_count += 1
if len(first_five) < 5: first_five.append( properties.get("BLKLOT") )
elapsed = time.perf_counter() - start
print(f"Total parcels: {total:,}") print(f"Market Street parcels: {market_count:,}") print(f"First five parcel IDs: {first_five}") print(f"Time: {elapsed:.2f} seconds")
Total parcels: 206,560 Market Street parcels: 808 First five parcel IDs: ['0265003', '0265004', '0265005', '0290012', '0291001'] Time: 4.58 seconds
我们不再需要:
或:
features = data["features"]
而是由程序直接从解析器处理每个要素:
for feature in ijson.items( f, "features.item" ):
在任何时刻,我们主要需要内存存储:
当前要素 + ijson解析器缓冲区 + 小型计数器 + 五个保存的ID
我们不需要为完整数据集分配内存。
运行相同的内存测试:
Line # Mem usage Increment Occurrences Line Contents ============================================================= 5 43.8 MiB 43.8 MiB 1 @profile 6 def process_file(): 7 8 43.8 MiB 0.0 MiB 1 total = 0 9 43.8 MiB 0.0 MiB 1 market_count = 0 10 11 46.1 MiB 0.0 MiB 2 with open("citylots.json", "rb") as f: 12 13 46.1 MiB 2.2 MiB 206562 for feature in ijson.items( 14 43.8 MiB 0.0 MiB 1 f, 15 43.8 MiB 0.0 MiB 1 "features.item" 16 ): 17 18 46.1 MiB 0.0 MiB 206560 total += 1 19 20 if ( 21 46.1 MiB 0.1 MiB 413120 feature["properties"] 22 46.1 MiB 0.0 MiB 206560 .get("STREET") == "MARKET" 23 ): 24 45.8 MiB 0.0 MiB 808 market_count += 1 25 26 27 46.1 MiB 0.0 MiB 1 print("Total parcels:", total) 28 46.1 MiB 0.0 MiB 1 print("Market Street parcels:", market_count)
现在将峰值内存使用量与 json.load() 的结果进行对比。
方法对比
输入文件
峰值内存
处理方式
json.load()
181 MB
808.9 MiB
加载全部数据
46.1 MiB
流式处理记录
差异
相同文件
约少使用 762.8 MiB 内存
更高效的处理方式
重要行为应保持一致:ijson 主要优势在于这种更稳定的内存占用特征。
这并不意味着ijson在所有情况下都会更快。当可用RAM充足时,json.load()有时可以非常快速地解析文档。ijson的主要优势在于,内存消耗不再需要随着完整JSON文档的大小而增长。
## 总结
大型JSON文件并不一定需要消耗大量内存。
问题往往不在于JSON格式本身,而在于我们选择处理它的方式。
在本教程中,我们使用了一个约181MB的真实旧金山土地地块数据集。
使用Python标准库:
json.load(f)
必须将整个数据集解析为Python对象后,分析才能开始。
这包括数千个嵌套的字典、列表、属性值、多边形和坐标,而这些内容我们的特定任务甚至根本不需要。
使用:
ijson.items( f, "features.item" )
彻底改变了处理模式。
我们不再采用:
加载所有内容 → 处理
而是使用:
读取 → 处理 → 丢弃
关键要点很简单:
> 如果你的任务只需要每次处理一条记录,通常没有理由一次性加载所有记录。
Kanwal Mehreen 是一名机器学习工程师和技术作家,对数据科学以及人工智能与医学的交叉领域充满热情。她合著了电子书《用ChatGPT最大化生产力》。作为2022年APAC地区Google Generation学者,她倡导多样性和学术卓越。她还被认定为Teradata科技多样性学者、Mitacs Globalink研究学者和哈佛WeCode学者。Kanwal是变革的坚定倡导者,她创立了FEMCodes组织,致力于赋能STEM领域的女性。
### 更多相关内容
- 数据科学生命周期流程
- 如何用Python清理杂乱的CSV文件:初学者指南
- 如何用Python写入文件:初学者指南
- 用Python的Pathlib组织、搜索和备份文件
- 如何在Bash中管理文件和目录
- 5个有用的DIY Python函数用于JSON解析和处理
<hr class="grey-line"><br> <div><h3>我们推荐的5门免费课程</h3><br> </div>
Mailchimp for WordPress v4.14.1 - https://wordpress.org/plugins/mailchimp-for-wp/
/ Mailchimp for WordPress插件
你可以从这里开始编辑。
如果评论已关闭。
<= 上一篇
#content end
<script type="text/javascript">kda_sid_write(kda_sid_n);</script>
### 最新文章
- 如何用ijson在Python中处理大型JSON文件
- Google开源Harness²:无需重新训练的自我改进AI代理
- 使用Scikit-LLM进行实体识别:无需重新训练的AI代理技能
- 2026年成为AI产品经理的路线图
- 开发者必备的5个Docker容器
## 热门文章
- 开发者必备的5个Docker容器
- 7个可替代付费订阅的开源AI工具
- AI软件克隆的兴起:为什么REA和ArtCraft正在病毒式传播
- AI代理技能的最佳5个GitHub仓库
- LLM推理工程的5个有趣项目
- 2026年掌握代理AI系统的路线图
- Claude Haiku 5.5:新功能及如何用于快速、低成本的AI工作流
- 2026年可使用的5个免费LLM API提供商
- 2026年值得关注的10个Hugging Face模型
- 信任AI生成代码前需要运行的7项检查
#content_wrapper end
© 2026
Guiding Tech Media
|
关于
联系我们
广告合作
隐私政策
服务条款
2026年10月22日由
blank
不,谢谢!
/.main_wrapper
<script defer type="text/javascript" src="https://s7.addthis.com/js/300/addthis_widget.js#pubid=gpsaddthis"></script>
noptimize
/noptimize