python ijson 不能同时处理多个元素
python ijson not working on multiple element at once
我有数千个非常大的 JSON 文件需要处理特定元素。为了避免内存过载,我使用了一个名为 ijson 的 python 库,当我只处理 json 文件中的单个元素时它工作正常,但当我尝试一次处理多个元素时它通过
IncompleteJSONError: parse error: premature EOF
部分JSON:
{
"info": {
"added": 1631536344.112968,
"started": 1631537322.81162,
"duration": 14,
"ended": 1631537337.342377
},
"network": {
"domains": [
{
"ip": "231.90.255.25",
"domain": "dns.msfcsi.com"
},
{
"ip": "12.23.25.44",
"domain": "teo.microsoft.com"
},
{
"ip": "87.101.90.42",
"domain": "www.msf.com"
}
]
}
}
工作代码:(打开多个文件)
my_file_list = [f for f in glob.glob("data/jsons/*.json")]
final_result = []
for filename in my_file_list:
row = {}
with open(filename, 'r') as f:
info = ijson.items(f, 'info')
for o in info:
row['added']= float(o.get('added'))
row['started']= float(o.get('started'))
row['duration']= o.get('duration')
row['ended']= float(o.get('ended'))
with open(filename, 'r') as f:
domains = ijson.items(f, 'network.domains.item')
domain_count = 0
for domain in domains:
domain_count+=1
row['domain_count'] = domain_count
失败代码:(单个文件打开)
my_file_list = [f for f in glob.glob("data/jsons/*.json")]
final_result = []
for filename in my_file_list:
row = {}
with open(filename, 'r') as f:
info = ijson.items(f, 'info')
for o in info:
row['added']= float(o.get('added'))
row['started']= float(o.get('started'))
row['duration']= o.get('duration')
row['ended']= float(o.get('ended'))
domains = ijson.items(f, 'network.domains.item')
domain_count = 0
for domain in domains:
domain_count+=1
row['domain_count'] = domain_count
不确定这就是我json 无法同时处理多个 json 元素的原因 。
此外,让我知道任何其他 python 包或任何可以处理大尺寸 json 而没有内存问题的示例。
我认为发生这种情况是因为您已经完成从文件中读取 IO 流,您已经读完了,并且已经在请求另一个查询。
你可以做的是在第二次查询之前将光标重置到0位置:
f.seek(0)
我在评论中说您也应该尝试 json-stream
,但这不是 ijson
或 json-stream
错误,它是 TextIO 功能。
这相当于您第二次打开文件。
如果你不想这样做,那么也许你应该看看遍历 JSON 的每个部分,然后为每个对象决定它是否具有 info
或 network.domains.item
.
虽然上面的答案是正确的,但您可以做得更好:如果您知道 JSON 文件的结构并且可以依赖它,您可以利用它来发挥自己的优势,并且只读取文件一次。
ijson
有一个偶数 interception mechanism,那里的例子与你想要实现的非常相似。在您的情况下,您想要获取 info
值,然后遍历 network.domains.item
并计算它们。应该这样做:
row = {}
with open(filename, 'r') as f:
parse_events = ijson.parse(f, use_float=True)
for prefix, event, value in parse_events:
if prefix == 'info.added':
row['added'] = value
elif prefix == 'info.started':
row['started'] = value
elif prefix == 'info.duration':
row['duration'] = value
elif prefix == 'info.ended':
row['ended'] = value
elif prefix == 'info' and event == 'end_map':
break
row['domain_count'] = sum(1 for _ in ijson.items(parse_events, 'network.domains.item'))
注意方法:
ijson.items
是 ijson.parse
. 的结果
use_float=True
让您不必自己将值转换为 float
。
- 可以通过
sum()
-ing 1
对来自 ijson.items
的每个项目进行计数,这样您就不必自己手动循环。
我有数千个非常大的 JSON 文件需要处理特定元素。为了避免内存过载,我使用了一个名为 ijson 的 python 库,当我只处理 json 文件中的单个元素时它工作正常,但当我尝试一次处理多个元素时它通过
IncompleteJSONError: parse error: premature EOF
部分JSON:
{
"info": {
"added": 1631536344.112968,
"started": 1631537322.81162,
"duration": 14,
"ended": 1631537337.342377
},
"network": {
"domains": [
{
"ip": "231.90.255.25",
"domain": "dns.msfcsi.com"
},
{
"ip": "12.23.25.44",
"domain": "teo.microsoft.com"
},
{
"ip": "87.101.90.42",
"domain": "www.msf.com"
}
]
}
}
工作代码:(打开多个文件)
my_file_list = [f for f in glob.glob("data/jsons/*.json")]
final_result = []
for filename in my_file_list:
row = {}
with open(filename, 'r') as f:
info = ijson.items(f, 'info')
for o in info:
row['added']= float(o.get('added'))
row['started']= float(o.get('started'))
row['duration']= o.get('duration')
row['ended']= float(o.get('ended'))
with open(filename, 'r') as f:
domains = ijson.items(f, 'network.domains.item')
domain_count = 0
for domain in domains:
domain_count+=1
row['domain_count'] = domain_count
失败代码:(单个文件打开)
my_file_list = [f for f in glob.glob("data/jsons/*.json")]
final_result = []
for filename in my_file_list:
row = {}
with open(filename, 'r') as f:
info = ijson.items(f, 'info')
for o in info:
row['added']= float(o.get('added'))
row['started']= float(o.get('started'))
row['duration']= o.get('duration')
row['ended']= float(o.get('ended'))
domains = ijson.items(f, 'network.domains.item')
domain_count = 0
for domain in domains:
domain_count+=1
row['domain_count'] = domain_count
不确定这就是我json 无法同时处理多个 json 元素的原因
此外,让我知道任何其他 python 包或任何可以处理大尺寸 json 而没有内存问题的示例。
我认为发生这种情况是因为您已经完成从文件中读取 IO 流,您已经读完了,并且已经在请求另一个查询。
你可以做的是在第二次查询之前将光标重置到0位置:
f.seek(0)
我在评论中说您也应该尝试 json-stream
,但这不是 ijson
或 json-stream
错误,它是 TextIO 功能。
这相当于您第二次打开文件。
如果你不想这样做,那么也许你应该看看遍历 JSON 的每个部分,然后为每个对象决定它是否具有 info
或 network.domains.item
.
虽然上面的答案是正确的,但您可以做得更好:如果您知道 JSON 文件的结构并且可以依赖它,您可以利用它来发挥自己的优势,并且只读取文件一次。
ijson
有一个偶数 interception mechanism,那里的例子与你想要实现的非常相似。在您的情况下,您想要获取 info
值,然后遍历 network.domains.item
并计算它们。应该这样做:
row = {}
with open(filename, 'r') as f:
parse_events = ijson.parse(f, use_float=True)
for prefix, event, value in parse_events:
if prefix == 'info.added':
row['added'] = value
elif prefix == 'info.started':
row['started'] = value
elif prefix == 'info.duration':
row['duration'] = value
elif prefix == 'info.ended':
row['ended'] = value
elif prefix == 'info' and event == 'end_map':
break
row['domain_count'] = sum(1 for _ in ijson.items(parse_events, 'network.domains.item'))
注意方法:
ijson.items
是ijson.parse
. 的结果
use_float=True
让您不必自己将值转换为float
。- 可以通过
sum()
-ing1
对来自ijson.items
的每个项目进行计数,这样您就不必自己手动循环。