【问题标题】:Using python ijson to read a large json file with multiple json objects使用 python ijson 读取包含多个 json 对象的大型 json 文件
【发布时间】:2016-05-13 02:26:49
【问题描述】:

我正在尝试使用 ijson 包解析一个大的 (~100MB) json 文件,它允许我以有效的方式与文件交互。然而,在写了一些这样的代码之后,

with open(filename, 'r') as f:
    parser = ijson.parse(f)
    for prefix, event, value in parser:
        if prefix == "name":
            print(value)

我发现代码只解析文件的第一行,而不解析文件的其余行!!

这是我的 json 文件的一部分的样子:

{"name":"accelerator_pedal_position","value":0,"timestamp":1364323939.012000}
{"name":"engine_speed","value":772,"timestamp":1364323939.027000}
{"name":"vehicle_speed","value":0,"timestamp":1364323939.029000}
{"name":"accelerator_pedal_position","value":0,"timestamp":1364323939.035000}

在我看来,ijson 只解析一个 json 对象。

有人可以建议如何解决这个问题吗?

【问题讨论】:

  • 嗯,你提供的块看起来像一个 set JSONs。那就是你应该逐行阅读并单独解析它。
  • BTW 因为每一行都很短,所以不需要ijson,可以使用json.loads()

标签: python json


【解决方案1】:

由于提供的块看起来更像是一组行,每行都组成一个独立的 JSON,因此应该对其进行相应的解析:

# each JSON is small, there's no need in iterative processing
import json 
with open(filename, 'r') as f:
    for line in f:
        data = json.loads(line)
        # data[u'name'], data[u'engine_speed'], data[u'timestamp'] now
        # contain correspoding values

【讨论】:

  • 感谢您的回答,我在问这是否不会将孔文件加载到 RAM 中? ,如果它一次只加载一行,那就太棒了
  • 当然for line in f: 一次读取一行。检查stackoverflow.com/questions/17246260/…
  • 如何在 ijson 中处理自定义编码和解码?我可以用 json 和 cls= 参数很容易地做到这一点,它是如何在 ijson 中完成的?有链接吗?谢谢!
【解决方案2】:

很遗憾,ijson 库(截至 2018 年 3 月的 v2.3)无法处理解析多个 JSON 对象。它只能处理 1 个整体对象,如果您尝试解析第二个对象,则会收到错误:"ijson.common.JSONError: Additional data"。在此处查看错误报告:

这是一个很大的限制。但是,只要在每个 JSON 对象后有换行符(换行符),就可以独立逐行解析每个对象,如下所示:

import io
import ijson

with open(filename, encoding="UTF-8") as json_file:
    cursor = 0
    for line_number, line in enumerate(json_file):
        print ("Processing line", line_number + 1,"at cursor index:", cursor)
        line_as_file = io.StringIO(line)
        # Use a new parser for each line
        json_parser = ijson.parse(line_as_file)
        for prefix, type, value in json_parser:
            print ("prefix=",prefix, "type=",type, "value=",value)
        cursor += len(line)

您仍在流式传输文件,而不是将其完全加载到内存中,因此它可以处理大型 JSON 文件。它还使用来自:How to jump to a particular line in a huge text file? 的线流技术并使用来自:Accessing the index in 'for' loops?enumerate()

【讨论】:

    猜你喜欢
    • 2018-08-14
    • 2019-01-31
    • 2018-09-22
    • 2021-03-03
    • 1970-01-01
    • 2020-12-23
    • 2022-01-12
    • 1970-01-01
    相关资源
    最近更新 更多