我有这个庞大的json文件(8gb),当我尝试将其读入Python时,我的内存不足。我如何使用ijson或其他一些对大型json文件更有效的库来实现类似的过程?
import pandas as pd
#There are (say) 1m objects - each is its json object - within in this file.
with open('my_file.json') as json_file:
data = json_file.readlines()
#So I take a list of these json objects
list_of_objs = [obj for obj in data]
#But I only want about 200 of the json objects
desired_data = [obj for obj in list_of_objs if object['feature']=="desired_feature"]
我如何使用ijson或类似的东西实现这个?有没有办法可以在不读取整个JSON文件的情况下提取我想要的对象?
该文件是一个对象列表,如:
{
"review_id": "zdSx_SD6obEhz9VrW9uAWA",
"user_id": "Ha3iJu77CxlrFm-vQRs_8g",
"business_id": "tnhfDv5Il8EaGSXZGiuQGg",
"stars": 4,
"date": "2016-03-09",
"text": "Great place to hang out after work: the prices are decent, and the ambience is fun. It's a bit loud, but very lively. The staff is friendly, and the food is good. They have a good selection of drinks.",
"useful": 0,
"funny": 0,
}
答案 0 :(得分:1)
该文件是一个对象列表
这有点模棱两可。查看代码片段,看起来您的文件在每行上都包含单独的JSON对象。这与以-Werror
开头的实际JSON数组不同,以[
结尾且项目之间有]
。
对于每行json文件,它就像:
一样简单,
请注意差异:
import json
from itertools import islice
with(open(filename)) as f:
objects = (json.loads(line) for line in f)
objects = islice(objects, 200)
,文件对象本身是一个可以产生单独行的迭代.readlines()
而不是(..)
中的括号[..]
创建一个惰性生成器表达式,而不是内存中包含所有行的Python列表(... for line in f)
将为您提供前200个项目,而无需进一步迭代。如果islice(objects, 200)
成为列表,您可以objects
现在,如果你的文件实际上是一个JSON数组,那么你确实需要ijson:
objects[:200]
import ijson # or choose a faster backend if needed
from itertools import islice
with open(filename) as f:
objects = ijson.items(f, 'item')
objects = islice(objects, 200)
在解析的数组上返回一个惰性迭代器。第二个参数中的ijson.items
表示“顶级数组中的每个项目”。
答案 1 :(得分:0)
问题在于,并非所有JSON都具有良好的格式,您不能依赖逐行解析来提取对象。 我将您的“接受标准”理解为“只想收集指定键包含指定值的JSON对象”。例如,如果该人的姓名为“Bob”,则仅收集有关某人的对象。以下函数将提供符合条件的所有对象的列表。解析是逐个字符完成的(在C中效率更高,但Python仍然相当不错)。这应该更加健壮,因为它不关心换行符,格式化等。我在带有1,000,000个对象的格式化和未格式化的JSON上测试了它。
for (TreeNode child : children) {
child.setParent(this);
}