在不加载i的情况下将Python字典列表附加到文件中

2024-04-18 06:35:34 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我需要一个包含字典列表的数据库文件:

文件:

[
  {"name":"Joe","data":[1,2,3,4,5]},
  {   ...                         },
           ...
]

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

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


Tags: 文件方法函数name数据库json编辑列表
3条回答

如果需要保持文件是有效的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编码文件以及大小(5gb)的虚拟文件进行测试。

如果还导入了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)。

可以使用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}

相关问题 更多 >