我正在尝试加载一个填充了JSON字符串的大文件(大小为2GB),由换行符分隔。例如:
{
"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
对象,因为我逐行读取文件?谢谢!
答案 0 :(得分:27)
此时只需读取每一行并构造一个json对象:
with open(file_path) as f:
for line in f:
j_content = json.loads(line)
这样,你可以加载正确的完整json对象(前提是json对象中某处或json对象中没有\n
),并且在需要时创建每个对象时避免内存问题。 / p>
还有这个答案。:
答案 1 :(得分:7)
这适用于您提供的特定文件格式。如果您的格式发生变化,那么您需要更改行的解析方式。
{
"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回调方法。
答案 2 :(得分:7)
contents = open(file_path, "r").read()
data = [json.loads(str(item)) for item in contents.strip().split('\n')]
答案 3 :(得分:1)
不得不从AWS S3读取一些数据并解析换行符分隔的jsonl文件。我的解决方案是使用splitlines
代码:
for line in json_input.splitlines():
one_json = json.loads(line)
答案 4 :(得分:0)
只需逐行阅读并通过流分析e 如果文件的大小超过1GB,则您的骇客技巧(在每个JSON字符串之间加上逗号,并在开头和结尾的方括号之间添加逗号以使其成为正确的列表)对内存不友好,因为整个内容将落入RAM。
答案 5 :(得分:0)
逐行阅读方法是很好的,如上面的一些答案所述。
但是,我建议在多个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
,并解析整个文件:-)。
答案 6 :(得分:0)
这扩展了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。