将Python字典列表附加到文件而不加载它

将Python字典列表附加到文件而不加载它,python,json,pickle,Python,Json,Pickle,假设我需要一个数据库文件,其中包含一系列字典: 文件: 我需要一个函数来接收如上所示的字典列表,并将其附加到文件中。有没有办法做到这一点,比如说使用json(或任何其他方法),而不加载文件 编辑1: 注意:我需要的是在光盘上已经存在的文件中添加新的字典。您可以使用json转储dict,每行一个。现在,每一行都是您编写的一个json dict。您失去了外部列表,但可以通过简单的附加操作将记录添加到现有文件中 import json import os def append_record(reco

假设我需要一个数据库文件,其中包含一系列字典:

文件:

我需要一个函数来接收如上所示的字典列表,并将其附加到文件中。有没有办法做到这一点,比如说使用json(或任何其他方法),而不加载文件

编辑1:
注意:我需要的是在光盘上已经存在的文件中添加新的字典。

您可以使用json转储dict,每行一个。现在,每一行都是您编写的一个json dict。您失去了外部列表,但可以通过简单的附加操作将记录添加到现有文件中

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}

如果需要保持文件为有效的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)) )
这将同时打开这两个文件。然后,它转到文件的结尾(从结尾算起零个字节)以找出文件结尾的位置(相对于文件的开头),并返回最后一个字节,这在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)) )

它将文件的字节长度定义为小于一个字节的位置(如前一个示例中所示)。

如果您希望不实际加载文件,那么使用
json
执行此操作确实不是正确的方法。你可以使用一个内存映射文件,但永远不要将文件加载到内存中,
memmap
数组可以打开文件并在“磁盘”上构建一个数组,而无需将任何内容加载到内存中

创建dict的内存映射数组:

>>> 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)。

使用与user3500511相同的方法

假设我们有两个字典列表(dicts,dicts2)。dict被转换为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()

“不加载”是什么意思?一种方法是将文件加载到内存中,将新列表附加到其中,然后将结果转储回光盘。是否可以只将新列表写入光盘,将其附加到文件末尾,而不将文件加载到内存中?这可能很有用:将新的dict加载到新文件中,然后可能合并这两个文件?在这里,看起来您实际上并没有将字典附加到光盘上的现有文件中,而是在代码中创建所有字典并将它们写入文件。我需要的是将它们附加到现有文件中。我可能应该注意到,在我最初的问题中。不,它会根据您的需要附加到文件中。for循环只是一个程序的演示,该程序将记录多次附加到文件中。运行演示两次,您将获得更多的记录。为了清晰起见,我将进行编辑。如果你不想使用漂亮的json(如果你想的话,这会使组装部分变得更加困难),这是一个很好的解决方案@ilius-是的,记录文件不应该是漂亮的!这实际上是一个你想用什么作为记录分隔符的问题。如果您没有很好地打印,那么json将不会添加任何新行,这是一个很好的分隔符(我在这里就是这么做的)。如果您想要漂亮的打印,您可以选择类似“\n--\n”的内容,但您必须扫描它,然后自己进行记录屏蔽。
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()