【问题标题】:AWS Sagemaker output how to read file with multiple json objects spread out over multiple linesAWS Sagemaker 输出如何读取分布在多行的多个 json 对象的文件
【发布时间】:2021-10-30 21:29:10
【问题描述】:

我有一堆像这样的 json 文件

{"vector": [0.017906909808516502, 0.052080217748880386, -0.1460590809583664, ], "word": "blah blah blah"}
{"vector": [0.01027186680585146, 0.04181386157870293, -0.07363887131214142, ], "word": "blah blah blah"}
{"vector": [0.011699287220835686, 0.04741542786359787, -0.07899319380521774, ], "word": "blah blah blah"}

我可以阅读的内容

f = open(file_name)
data = []
for line in f:
   data.append(json.dumps(line))

但是我有另一个文件,输出是这样的

{
    "predictions": [[0.875780046, 0.124219939], [0.892282844, 0.107717164], [0.887681246, 0.112318777]
    ]
}
{
    "predictions": [[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]
    ]
}
{
    "predictions": [[0.391415, 0.608585], [0.992118478, 0.00788147748], [0.0, 1.0]
    ]
}

即json 被格式化为多行,所以我不能简单地逐行读取 json。有没有一种简单的方法来解析这个?还是我必须编写一些东西将每个 json 对象逐行拼接在一起,并且 json.loads 是什么?

【问题讨论】:

    标签: python json amazon-sagemaker


    【解决方案1】:

    嗯,据我所知,很遗憾无法使用json.loads 加载JSONL 格式的数据。不过,一种选择是提供一个辅助函数,可以将其转换为有效的 JSON 字符串,如下所示:

    import json
    
    string = """
    {
        "predictions": [[0.875780046, 0.124219939], [0.892282844, 0.107717164], [0.887681246, 0.112318777]
        ]
    }
    {
        "predictions": [[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]
        ]
    }
    {
        "predictions": [[0.391415, 0.608585], [0.992118478, 0.00788147748], [0.0, 1.0]
        ]
    }
    """
    
    
    def json_lines_to_json(s: str) -> str:
        # replace the first occurrence of '{'
        s = s.replace('{', '[{', 1)
    
        # replace the last occurrence of '}
        s = s.rsplit('}', 1)[0] + '}]'
    
        # now go in and replace all occurrences of '}' immediately followed
        # by newline with a '},'
        s = s.replace('}\n', '},\n')
    
        return s
    
    
    print(json.loads(json_lines_to_json(string)))
    

    打印:

    [{'predictions': [[0.875780046, 0.124219939], [0.892282844, 0.107717164], [0.887681246, 0.112318777]]}, {'predictions': [[0.0, 1.0], [0.0, 1.0], [0.0, 1.0]]}, {'predictions': [[0.391415, 0.608585], [0.992118478, 0.00788147748], [0.0, 1.0]]}]
    

    注意:您的第一个示例实际上看起来不像是有效的 JSON(或者至少是我理解的 JSON 行)。特别是,由于最后一个数组元素后的尾随逗号,这部分似乎无效:

    {"vector": [0.017906909808516502, 0.052080217748880386, -0.1460590809583664, ], ...}
    

    为确保调用辅助函数后有效,您还需要删除结尾的逗号,因此每一行的格式如下:

    {"vector": [0.017906909808516502, 0.052080217748880386, -0.1460590809583664 ], ...},
    

    似乎还有一个similar question,他们建议在换行符上拆分并在每一行上调用json.loads;实际上,在每个对象上多次调用 json.loads 应该(稍微)性能较低,而不是在列表中调用一次,如下所示。

    from timeit import timeit
    import json
    
    
    string = """\
    {"vector": [0.017906909808516502, 0.052080217748880386, -0.1460590809583664 ], "word": "blah blah blah"}
    {"vector": [0.01027186680585146, 0.04181386157870293, -0.07363887131214142 ], "word": "blah blah blah"}
    {"vector": [0.011699287220835686, 0.04741542786359787, -0.07899319380521774 ], "word": "blah blah blah"}\
    """
    
    
    def json_lines_to_json(s: str) -> str:
    
        # Strip newlines from end, then replace all occurrences of '}' followed
        # by a newline, by a '},' followed by a newline.
        s = s.rstrip('\n').replace('}\n', '},\n')
    
        # return string value wrapped in brackets (list)
        return f'[{s}]'
    
    
    n = 10_000
    
    print('string replace:        ', timeit(r'json.loads(json_lines_to_json(string))', number=n, globals=globals()))
    print('json.loads each line:  ', timeit(r'[json.loads(line) for line in string.split("\n")]', number=n, globals=globals()))
    

    结果:

    string replace:         0.07599360000000001
    json.loads each line:   0.1078384
    

    【讨论】:

    • 感谢您的确认。想看看我是否能以更清洁的方式做到这一点,但看起来我必须做一个辅助功能。感谢您的建议
    • @LXandor 没问题,很高兴我能帮上忙。我也在做一个快速的谷歌搜索,发现这个other question 看起来也在询问关于读取 JSONL 数据的问题,但他们在那里提出了一种不同的方法。我还更新了我的帖子以展示这种方法,这种方法效率稍低,但这样做也容易得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 2021-03-03
    • 2020-12-25
    相关资源
    最近更新 更多