如何从大文件中读取行分隔的JSON(逐行)

vbopmzt1  于 2023-11-20  发布在  其他
关注(0)|答案(9)|浏览(148)

我正在尝试加载一个大文件(2GB大小),其中填充了JSON字符串,并以换行符分隔。

{
    "key11": value11,
    "key12": value12,
}
{
    "key21": value21,
    "key22": value22,
}
…

字符串
我现在导入它的方式是:

content = open(file_path, "r").read() 
j_content = json.loads("[" + content.replace("}\n{", "},\n{") + "]")


这看起来像是一个技巧(在每个JSON字符串之间添加逗号,并在开始和结束方括号中使其成为一个正确的列表)。
有没有更好的方法来指定JSON字符串(换行符\n而不是逗号,)?
另外,Python似乎不能为从2GB数据构建的对象正确分配内存,有没有一种方法可以在我逐行阅读文件时构建每个JSON对象?谢谢!

kx7yvsdv

kx7yvsdv1#

此时只需阅读每一行并构造一个json对象:

with open(file_path) as f:
    for line in f:
        j_content = json.loads(line)

字符串
通过这种方式,你加载了正确的完整的json对象(假设在json值的某个地方或json对象的中间没有\n),并且你避免了内存问题,因为每个对象都是在需要时创建的。
也有这样的答案:
https://stackoverflow.com/a/7795029/671543

dohp0rv5

dohp0rv52#

contents = open(file_path, "r").read() 
data = [json.loads(str(item)) for item in contents.strip().split('\n')]

字符串

fcy6dtqo

fcy6dtqo3#

这将适用于您指定的特定文件格式。如果您的格式更改,则需要更改行的解析方式。

{
    "key11": 11,
    "key12": 12
}
{
    "key21": 21,
    "key22": 22
}

字符串
只需逐行阅读,然后构建JSON块:

with open(args.infile, 'r') as infile:

    # Variable for building our JSON block
    json_block = []

    for line in infile:

        # Add the line to our JSON block
        json_block.append(line)

        # Check whether we closed our JSON block
        if line.startswith('}'):

            # Do something with the JSON dictionary
            json_dict = json.loads(''.join(json_block))
            print(json_dict)

            # Start a new block
            json_block = []


如果您有兴趣解析一个非常大的JSON文件,而不将所有内容保存到内存中,那么您应该考虑使用json.load API中的object_hook或object_pairs_hook回调方法。

8cdiaqws

8cdiaqws4#

这扩展了Cohen的答案:

content_object = s3_resource.Object(BucketName, KeyFileName)
file_buffer = io.StringIO()
file_buffer = content_object.get()['Body'].read().decode('utf-8')

json_lines = []
for line in file_buffer.splitlines():
    j_content = json.loads(line)
    json_lines.append(j_content)

df_readback = pd.DataFrame(json_lines)

字符串
这是假设整个文件都能容纳在内存中。如果文件太大,那么就必须修改为分块读取或使用Dask

3j86kqsm

3j86kqsm5#

必须从AWS S3读取一些数据并解析一个以换行符分隔的jsonl文件。
代码:

for line in json_input.splitlines():
     one_json = json.loads(line)

字符串

idfiyjo8

idfiyjo86#

逐行阅读的方法是好的,正如上面的一些答案中所提到的。
然而,在多个JSON树结构中,我建议分解为2个函数,以获得更健壮的错误处理。
比如说,

def load_cases(file_name):
    with open(file_name) as file:
        cases = (parse_case_line(json.loads(line)) for line in file)
        cases = filter(None, cases)
        return list(cases)

字符串
parse_case_line可以封装上面示例中所需的键解析逻辑,例如正则表达式匹配或特定于应用程序的要求。这也意味着您可以选择要解析出哪些json键值。
这种方法的另一个优点是filter处理json对象中间的多个\n,并解析整个文件:-)。

ekqde3dh

ekqde3dh7#

jq python库可以快速处理这种情况。
这是我的项目中的一个例子。在我的例子中,我有来自其他地方的文件对象。

import jq

raw = file.read().decode("utf-8")
for row in iter(jq.compile(".").input(text=raw)):
  print(row)

字符串
依赖项可以这样安装:

pip install jq


看看jq,它是一种简单的查询json对象的方法,在命令行或代码中。

l7wslrjt

l7wslrjt8#

使用Pandas 1.5.3:

pd.read_json( "path/to/json/delimited/file.json", lines=True )

字符串
为我工作;)
json delimited file + code to read it.

f1tvaqid

f1tvaqid9#

只需逐行读取并通过流解析e,而您的黑客技巧(在每个JSON字符串之间添加逗号以及开始和结束方括号以使其成为一个适当的列表)对于内存不友好,如果文件超过1GB,则整个内容将落在RAM上。

相关问题