#json #python-3.x #configuration #raspberry-pi4
#json #python-3.x #конфигурация #raspberry-pi4
Вопрос:
Я немного зациклен на проблеме, с которой я сталкиваюсь.
У меня есть программа на python, которая отправляет сигналы через интерфейс GPIO (Pi 4). Сигналы зависят от config.json
Макет json выглядит следующим образом:
{
"key1" : val1
"key2" : val2
"key3" : val3
}
Данные конфигурации передаются вызывающим абонентам в виде списков и сохраняются в виде файла конфигурации dict / json на устройстве для повторного использования, когда новая конфигурация не поступает.
Программа использует следующий фрагмент кода для чтения, редактирования и сохранения существующих или новых конфигураций:
def check_json(self, source: str, write=False, val1=940, val2=5, val3=10):
"""check_json checks whether there's an existing config on the machine and in the same folder/location
if it does exist, it gets returned to the caller. If it doesn't exist, a new file will be created
with preset data"""
if os.path.isfile(source):
if write:
try:
with open(source, "r ") as json_data: # update the existing values and save them
try:
config_data = js.load(json_data)
config_data["key1"] = val1
config_data["key2"] = val2
config_data["key3"] = val3
print(config_data)
json_data.seek(0)
json_data.truncate()
js.dump(config_data, json_data, indent=2)
json_data.flush()
except TypeError:
pass
except TypeError:
pass
else:
json_data = open(source, "r")
dict_data = js.load(json_data)
config_data = [dict_data["light_lvl"],
dict_data["on_time"], dict_data["off_time"]]
json_data.close()
return config_data
# create new with presets if json config does not exist
else:
json_data = open(source, "w")
dict_data = {"key1": val1,
"key2": on_time, "key3": val}
js.dump(dict_data, json_data, indent=2)
json_data.flush()
json_data.close()
return self.check_json(source)
Как только поступает новая конфигурация, программа завершает работу со следующей ошибкой:
"key1" = config_data[0]
TypeError: 'NoneType' object is not subscriptable
Ошибка возникает, даже если json поступает с неповрежденным содержимым. Я попытался использовать несколько попыток и исключения как видимые в надежде, что он просто продолжит чтение новых данных конфигурации на новой итерации. Блоки try и except немного не помогли, и я не знаю, как еще я мог это исправить,
Любой ввод, советы / рекомендации приветствуются
Ответ №1:
Похоже, мой подход был неправильным. Я запрограммировал свое решение с идеей, что я могу просто получить доступ к своим значениям без каких-либо забот. Но это не так, поскольку файл несколько изменчив, в том смысле, что он все еще может находиться в процессе «получения».
Попытка получить значения файла, который все еще не получен полностью, может привести только к проблемам. Убрав это с пути, я вернулся к чертежной доске и немного пересмотрел свою концепцию.
class FileOps:
def __init__(self, file_name: str):
self.file_name = file_name
self.config_name = "config.json"
self.preset_config = {"key1" : val1, "key2" : val2, "key3" : val3}
def save_config(self):
"saves the newer config file and deletes it in order to avoid clutter."
if isfile(self.file_name):
with open(self.config_name, "w") as file:
js.dump(self.pass_new(), file, indent=2)
remove(self.file_name) # delete the newly arrived config to prevent clutter
def read_config(self):
"""pass the existing config over to the caller if present.
Creates a preset config using the field "preset_config" if config.json doesn't exist """
if not isfile(self.config_name):
with open(self.config_name,"w") as file:
js.dump(self.preset_config, file, indent=2)
return self.preset_config # return the preset config for now
with open(self.config_name, "r") as file:
json_string = ""
for line in file:
json_string = line
return js.loads(json_string)
def pass_new(self):
"""checks if a new config is present and passes the data through to the caller"""
if isfile(self.file_name):
with open(self.file_name, "r") as file:
json_string = ""
for line in file:
json_string = line
return js.loads(json_string)
Я разделил операции чтения файлов на другой файл и класс, чтобы все было конкретным и кратким, и я просто запрограммировал его так, чтобы файл считывался построчно, а не мгновенно пытался его разобрать. Это устранило мою проблему, TypeError: 'NoneType' object is not subscriptable
а также правильно передало информацию.
Класс FIleOps передается основному классу как композиционное отношение и вызывается при необходимости через простой объект.