假设我需要一个包含字典列表的数据库文件:
文件:
[
{"name":"Joe","data":[1,2,3,4,5]},
{ ... },
...
]
我需要有一个函数来接收如上所示的字典列表并将其附加到文件中。有没有办法实现这一点,比如使用json(或任何其他方法),而不加载文件?
EDIT1: 注意:我需要的是将新词典附加到光盘上现有的文件中。
答案 0 :(得分:20)
您可以使用json转储序列,每行一个。现在每行都是你写过的单个json词典。您松开了外部列表,但您可以添加带有简单附加到现有文件的记录。
import json
import os
def append_record(record):
with open('my_file', 'a') as f:
json.dump(record, f)
f.write(os.linesep)
# demonstrate a program writing multiple records
for i in range(10):
my_dict = {'number':i}
append_record(my_dict)
该列表可以稍后组装
with open('my_file') as f:
my_list = [json.loads(line) for line in f]
该文件看起来像
{"number": 0}
{"number": 1}
{"number": 2}
{"number": 3}
{"number": 4}
{"number": 5}
{"number": 6}
{"number": 7}
{"number": 8}
{"number": 9}
答案 1 :(得分:4)
如果需要保持文件有效json,可以按如下方式完成:
import json
with open (filepath, mode="r+") as file:
file.seek(0,2)
position = file.tell() -1
file.seek(position)
file.write( ",{}]".format(json.dumps(dictionary)) )
这将打开reading and writing的文件。然后,它到文件的末尾(从结尾开始的零字节)找出文件结束的位置(相对于文件的开头)并返回最后一个字节,这在json文件中应该代表字符]
。最后,它在结构中附加一个新字典,覆盖文件的最后一个字符并使其保持有效json。它不会将文件读入内存。使用Python 3.4.3中的ANSI和utf-8编码文件进行测试,包含小型和大型(5 GB)虚拟文件。
如果您还导入了os
模块,则为变体:
import os, json
with open (filepath, mode="r+") as file:
file.seek(os.stat(filepath).st_size -1)
file.write( ",{}]".format(json.dumps(dictionary)) )
它定义文件的字节长度,使其减少一个字节的位置(如上例所示)。
答案 2 :(得分:1)
如果您不想加载该文件,那么使用json
进行此操作并不是正确的方法。您可以使用内存映射文件......并且永远不会将文件实际加载到内存中 - memmap
数组可以打开文件并在“磁盘上”构建数组,而无需将任何内容加载到内存中。
创建一个内存映射的dicts数组:
>>> import numpy as np
>>> a = np.memmap('mydict.dat', dtype=object, mode='w+', shape=(4,))
>>> a[0] = {'name':"Joe", 'data':[1,2,3,4]}
>>> a[1] = {'name':"Guido", 'data':[1,3,3,5]}
>>> a[2] = {'name':"Fernando", 'data':[4,2,6,9]}
>>> a[3] = {'name':"Jill", 'data':[9,1,9,0]}
>>> a.flush()
>>> del a
现在读取数组,而不加载文件:
>>> a = np.memmap('mydict.dat', dtype=object, mode='r')
创建列表时,文件的内容会加载到内存中,但这不是必需的 - 您可以在不加载的情况下使用磁盘阵列。
>>> a.tolist()
[{'data': [1, 2, 3, 4], 'name': 'Joe'}, {'data': [1, 3, 3, 5], 'name': 'Guido'}, {'data': [4, 2, 6, 9], 'name': 'Fernando'}, {'data': [9, 1, 9, 0], 'name': 'Jill'}]
创建一个可以索引文件的内存映射数组需要一个可以忽略的时间(例如纳秒),而不管文件的大小(例如100 GB)。
答案 3 :(得分:0)
使用与user3500511相同的方法......
假设我们有两个字典列表(dicts,dicts2)。 dicts被转换为json格式的字符串。 Dicts保存到一个新文件 - test.json。重新打开Test.json,并使用正确的分隔符格式化字符串对象。使用重新格式化的对象,可以附加dict2,文件仍然保持JSON对象的正确结构。
import json
dicts = [{ "name": "Stephen", "Number": 1 }
,{ "name": "Glinda", "Number": 2 }
,{ "name": "Elphaba", "Number": 3 }
,{ "name": "Nessa", "Number": 4 }]
dicts2= [{ "name": "Dorothy", "Number": 5 }
,{ "name": "Fiyero", "Number": 6 }]
f = open("test.json","w")
f.write(json.dumps(dicts))
f.close()
f2 = open("test.json","r+")
f2.seek(-1,2)
f2.write(json.dumps(dicts2).replace('[',',',1))
f2.close()
f3 = open('test.json','r')
f3.read()