使用 python 在 .json 文件中存储数据的所有不同方法是啥?
Posted
技术标签:
【中文标题】使用 python 在 .json 文件中存储数据的所有不同方法是啥?【英文标题】:What are all the different ways of storing data in a .json file using python?使用 python 在 .json 文件中存储数据的所有不同方法是什么? 【发布时间】:2021-05-11 15:35:06 【问题描述】:我目前一直在为我的 discord.py 机器人开发警告系统。我一直做得很好,直到我意识到我不知道如何添加到文件而不是覆盖文件。我不想添加到文件的末尾,因为我希望它按不和谐公会分类,然后是公会成员。因此,当有人想要检查他们的警告时,它只会在调用该命令的特定行会中显示他们的警告。我的问题是将信息存储到 .json
文件的所有不同方式是什么?
例如:warn_list[str(ctx.guild.id)][member.id].add(stuff in here)
如示例中所示,我不想知道存储又名'a'
、'w'
等的不同模式。我想知道,如果有的话,可以在最后添加什么。喜欢.append()
或.add()
。我在 google 上查找了一个列表,但找不到我要查找的信息。任何帮助将不胜感激。
真诚地, 杀羚羊
【问题讨论】:
JSON 文件只是文本,JSON 只是基于文本的序列化格式。通常,您在 Python 中操作一些反序列化的数据结构,再次序列化整个事物并覆盖整个文件。您甚至可以操作表示 JSON 的字符串,但通常要避免这种情况。如果这种东西无法扩展,那么您正在寻找某种数据库,而不仅仅是 JSON 文件。 告诉我warn_list[str(ctx.guild.id)][member.id]
是什么对象,我会告诉你它支持什么功能。我无法在网上找到任何关于定制warn_list
的信息,所以我猜你自己创建了这个结构。如果你有地方可以捕获终端输出(比如一个日志文件),那么你总是可以print(dir(warn_list[str(ctx.guild.id)][member.id]))
,它会列出它支持的功能。
@RazzleShazl warn_list
当前为json.load
,代码行为warn_list = json.load(f)
。它的作用是在有人收到警告时将信息放入.json
文件中,但我希望它不会覆盖预先存在的数据,而只是添加到预先存在的数据中。
warn_list = json.load(f)
会将您保存的文件的内容反序列化为 python 对象。这是读取步骤。我猜在你的代码的某个地方,有一个反向事务,你的内存对象被序列化到保存的文件中。你能找到并分享那行代码吗?
@RazzleShazl 是的,with open('warnings.json', 'w') as f: json.dump(warn_list, f)
【参考方案1】:
如何添加持久化到 JSON 的自定义数据
您正在向字典添加数据,因此您将使用 dict[key] = value
添加数据,并使用 value = dict[key]
读取数据 1 。要添加到 list
的末尾,请使用 append()
。
你已经很接近你所拥有的了。让我们重构一下思路清晰:
warns_for_a_user = warn_list[str(ctx.guild.id)][member.id]
我们可以直接使用这个字典来存储关于这个member.id
的警告信息。我们需要一个数据结构,我认为list
符合要求(或dict
)。您可能需要这些警告中的时间信息,而时间似乎是一个合理的排序顺序和/或主键。
我想知道,如果有的话,最后可以加什么
通常不会直接修改.json
文件。修改.json
文件的唯一可靠方法是将整个内容导入内存,然后在修改后将其保存回.json
。
将.json
文件视为照片 或及时快照。如果场景发生了变化,您只需扔掉旧照片并拍摄另一张照片;如果状态已更新,我们只需将旧的warnings.json
丢弃并创建一个新的warnings.json
。
第 1 步:添加新字段并追加到新字段
鉴于我们有最新的warning
的信息,我们可以将其保存到用户的历史记录中:
# working with givens:
warning = "type": "spam", "count": "20", "timestamp": 1612756912.987963
if not history in warns_for_a_user:
warns_for_a_user['history'] = []
warns_for_a_user['history'].append([warning['timestamp'], warning])
您添加的这些新字段不应与任何内容冲突,因为它们是其他代码部分未知的定制字段。
如果您发现将每个警告包装在时间戳中很复杂,那是因为确实如此。但是,通常选择单个字段(或字段组合)作为整个对象的代表键。这有助于人类直接读取json文件,也可以简化处理逻辑。
第 2 步:读取新字段数据
稍后,用户想要查看他的警告。以下内容一次打印一个警告(日期时间代码来自SO):
import datetime
for epoch_time, warn in warns_for_a_user['history']:
_datetime = datetime.datetime.fromtimestamp(epoch_time)
_human_datetime = _datetime.strftime('%Y-%m-%d %H:%M:%S')
print(f"_human_datetime: [warn['count']x] warn['type']")
输出:
2021-02-07 20:01:52: [20x] spam
支持的数据类型
JSON 编码器文档有一个mapping 说明它如何将序列化的 JSON 数据转换为反序列化的 Python 对象。请注意,它将元组转换为列表。
检查warnings.json
如果您按照我的示例进行操作,您应该会在 warnings.json
的相应用户下看到以下添加:
"history": [[1612756912.987963, "count": 20, "type": "spam", "timestamp": 1612756912.987963]]
1 方括号表示法是__getitem__()
和__setitem__()
的语法糖
【讨论】:
好的,感谢您的精彩深入解释。我见过有人用这种方法来计数。我假设你只能这样做,因为否则它会覆盖,最好知道哪个警告。很抱歉没有尽快回复,因为我没有在我的电脑上,祝你有美好的一天! @killrebeest 我假设你只能这样做,因为否则它会覆盖,最好知道哪个警告 - 抱歉,我不太关注这个,这是我的问题吗?以上是关于使用 python 在 .json 文件中存储数据的所有不同方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
在 KivyMD Python 中将数据存储在 JSON 文件中时出错
将数据存储在 JSON 文件中时出现类型错误。(KivyMD Python)
python - 如何在python中附加一个列表时处理异常,其中包含从存储从.json文件读取的数据的dict读取的数据?