. json文件工作(读/写/变化)与Python动态



最近我开始重写我以前写的游戏。我主要关心的是试图修复它的主要问题是在单个文件上操作(导致崩溃和数据溢出)。

在构思更改概念时,我决定使用.json动态存储数据(就像"autosave"和材料的定期保存由用户完成)。我尝试使用json库来创建函数,使我能够轻松地读取和写入数据,以这样的方式:

从。json中读取特定变量->操作它,如果需要→只覆盖.json文件的特定部分

遗憾的是,不管我怎么做,我都不能让它读取。json文件,更不用说编辑值了。所有"json.dump()";到目前为止,我发现的例子试图在.json中编写新行或替换文件,而不是简单地编辑特定的值。我觉得在游戏的每个回合重写整个文件是没有效率的。

far(2个变量)使用的代码,分别导致没有控制台输出或使用_io。texttiowrapper,我不知道如何转换成有用的数据):

def json_read(path, element):
import json
with open(path) as json_file:
data = json.load(json_file)
data = dict(data[element])
print (data)
def json_read(path, element):
import json
json_file = open(path, "r")
print (json.load(json_file))

我想实现的主要目标是使函数在四个参数上操作,简化形式如下:

def json_change(path, element, change_type, change_value):
if change_type == "replacement":
#replace .json variable [element] value with [change_value]
elif change_type == "maths":
#do mathematic equation (.json variable value [element] + [change_value]) and write its result back
elif change_type == "var_addition":
#write new variable called [element] in the end of .json file with value of [change_value]

另一个函数将只是尝试从(path, element)参数中读取文件,它将返回值供json_change或其他元素进一步使用。如上所示,我已经试着介绍过了。

我建议你只使用json库。读取文件一次,偶尔保存一次,比方说每五分钟保存一次。也许你想在单例模式中创建一个新类。这将确保您拥有一个保存当前最新信息的对象,并且只有这个对象可以更新文件。

下面是这个类的快速草图:

# SaveFileHandler.py
import json

class _SaveFileHandler:
def __init__(self):
self._data = {}
self._path = ""
def read(self, path):
self._path = path
with open(path) as file:
self._data = json.load(file)
def write(self):
with open(self._path) as file:
json.dump(self._data, file)
# now for every value you want data to have do the following
# it allows you to check the value for errors and makes the usage more readable
@property
def key(self):
return self._data["key"]
@key.setter
def key(self, value):
self._data["key"] = value

# the is the only object you will ever use
save_file = _SaveFileHandler()

您也可以直接在init中读取保存文件,这将确保您的数据始终可用。

我自己找到了解决方案,以我想要的方式,下面是我最终使用的代码。

首先,我决定做两个功能具有相似的系统,但服务于不同的目的(一般保存和加载系统的数据;将显示仅保存一个,因为它们仅因使用的目录不同而不同)。参数如下所示:

  • name =播放器名称(保存在" saved/X"文件夹)
  • category = .json文件使用(有四个,每个保存(统计/任务/世界变化/库存)的不同方面)
  • dict_type =决定返回值是否是包含所有"变量"的字典;from save (True)或only selected变量(假的,违约)
  • element = specific "variable"(如果dict_type = True,可以是任何值)

在这里,我只是让函数读取特定文件并返回字典或变量;本身。我还为JSONDecoreError设置了安全门,所以如果。json(出于某种原因)为空,它将打印它。

def save_read(name, category, element, dict_type=False):
import json
final_path = "saves/" + name + "/in_use/" + category + ".json"
data = {}
try:
with open (final_path) as json_file:
data = json.load(json_file)
if dict_type == False:
return data[element]
else:
return data
except json.decoder.JSONDecodeError:
print ("JSON File: " + final_path + " does not have any arguments. Skipping.")

下面的代码用于更详细地管理"变量"。在保存文件中。它再次检查玩家的名字,类别和元素(都是相同的),但也有参数:

  • change_type =解释程序和函数运行(我们想做要么替换值,使其相对变化,甚至添加新的"variable"如果需要新)
  • change_value =我们使用的值,通常是int, str或boolean

因此取决于"change_type"论点,"change_value"用于不同的目的(或者根本不使用,如果我们完全保存/加载,在这个答案的底部解释)。

def save_change(name, category, element, change_type, change_value, in_use=True):
#in_use=True is for all data elements within game, =False for saving game, since it uses different directory
import json
if in_use == True:
final_path = "saves/" + name + "/in_use/" + category + ".json"

#simply replacing value with new one (usually for string variables)
if change_type == "replace":
temp_dict = save_read(name, category, element, True)
temp_dict[element] = change_value
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)

#math is intended to change value with +/- (use negative value to make it smaller)
elif change_type == "math":
temp_dict = save_read(name, category, element, True)
temp_dict[element] = temp_dict[element] + change_value
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)
#math, but for (*) [rare case]
elif change_type == "math*":
temp_dict = save_read(name, category, element)
temp_dict[element] = temp_dict[element] * change_value
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)
#math, but for (/) [rare case]
elif change_type == "math/":
temp_dict = save_read(name, category, element)
temp_dict[element] = temp_dict[element] / change_value
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)
#var_add is intended to be dict; can be useful with version_updater especially
elif change_type == "var_add":
temp_dict = save_read(name, category, element, True)
temp_dict.update (change_value)
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)
#var_add, but for deleting; change_value can be anything in this case
elif change_type == "var_del":
temp_dict = save_read(name, category, element, True)
temp_dict.remove (element)
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)
#for loading the game (uses load_read)
elif change_type == "game_load":
temp_dict = load_read(name, category, element, True)
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)
elif in_use == False:
#for game saving | 'element' and 'change_value' can be anything
if change_type == "game_save":
final_path = "saves/" + name + "/" + category + ".json"
temp_dict = save_read(name, category, element, True)
with open (final_path,'w') as file:
json.dump(temp_dict, file, indent = 2)

如果你想看到完整系统的精确代码(截至目前),也可以在GitHub上看到最新的工作提交。它使用:

  • system/json_management .py -用于一般管理(通信游戏<->"保存使用")
  • system/save_system/save_load.py -完整的保存/加载机制,运行玩家手动设置

它只是覆盖存档。json或"当前使用的游戏".jsons,取决于是加载还是保存。