Добавление данных в json файл в Python
Я пытаюсь создать функцию, которая будет добавлять записи в файл JSON. В конце концов, я хочу файл, который выглядит как
[{"name" = "name1", "url" = "url1"}, {"name" = "name2", "url" = "url2"}]
и т.д. Вот что у меня есть:
def add(args):
with open(DATA_FILENAME, mode='r', encoding='utf-8') as feedsjson:
feeds = json.load(feedsjson)
with open(DATA_FILENAME, mode='w', encoding='utf-8') as feedsjson:
entry = {}
entry['name'] = args.name
entry['url'] = args.url
json.dump(entry, feedsjson)
Это создает запись, такую как {"name"="some name", "url"="some url"}
. Но если я снова использую эту функцию add
с другим именем и URL, первая будет перезаписана. Что мне нужно сделать, чтобы добавить вторую (третью...) запись к первой?
РЕДАКТИРОВАТЬ: Первые ответы и комментарии к этому вопросу указали на очевидный факт, что я не использую feeds
в блоке записи. Я не вижу, как это сделать, хотя. Например, следующее явно не подойдет:
with open(DATA_FILENAME, mode='a+', encoding='utf-8') as feedsjson:
feeds = json.load(feedsjson)
entry = {}
entry['name'] = args.name
entry['url'] = args.url
json.dump(entry, feeds)
Ответы
Ответ 1
Вероятно, вы хотите использовать список JSON вместо словаря в качестве элемента верхнего уровня.
Итак, инициализируйте файл пустым списком:
with open(DATA_FILENAME, mode='w', encoding='utf-8') as f:
json.dump([], f)
Затем вы можете добавить новые записи в этот список:
with open(DATA_FILENAME, mode='w', encoding='utf-8') as feedsjson:
entry = {'name': args.name, 'url': args.url}
feeds.append(entry)
json.dump(feeds, feedsjson)
Обратите внимание, что это будет медленным, потому что вы будете переписывать полное содержимое файла каждый раз, когда вы вызываете add
. Если вы вызываете его в цикле, подумайте о том, чтобы добавить все фиды в список заранее, а затем записать список за один раз.
Ответ 2
json может не быть лучшим выбором для форматов на диске; Проблема, связанная с добавлением данных, является хорошим примером того, почему это может быть. В частности, объекты json имеют синтаксис, который означает, что весь объект должен быть прочитан и проанализирован, чтобы понять любую его часть.
К счастью, есть много других вариантов. Особенно простой - CSV; который хорошо поддерживается стандартной библиотекой python. Самым большим недостатком является то, что он хорошо работает только для текста; он требует дополнительных действий со стороны программиста для преобразования значений в числа или другие форматы, если это необходимо.
Другим вариантом, который не имеет этого ограничения, является использование базы данных sqlite, которая также имеет встроенную поддержку в python. Это, вероятно, будет большим отступлением от кода, который у вас уже есть, но он более естественно поддерживает модель "изменить немного", которую вы, по-видимому, пытаетесь построить.
Ответ 3
Добавить запись к содержимому файла, если файл существует, в противном случае добавить запись в пустой список и записать в файл:
a = []
if not os.path.isfile(fname):
a.append(entry)
with open(fname, mode='w') as f:
f.write(json.dumps(a, indent=2))
else:
with open(fname) as feedsjson:
feeds = json.load(feedsjson)
feeds.append(entry)
with open(fname, mode='w') as f:
f.write(json.dumps(feeds, indent=2))
Ответ 4
Использование a
вместо w
должно позволить вам обновить файл вместо создания нового/перезаписать все в существующем файле.
См. этот ответ для разницы в режимах.
Ответ 5
Одним из возможных решений является конкатенация вручную, вот несколько полезных кодов:
import json
def append_to_json(_dict,path):
with open(path, 'ab+') as f:
f.seek(0,2) #Go to the end of file
if f.tell() == 0 : #Check if file is empty
f.write(json.dumps([_dict]).encode()) #If empty, write an array
else :
f.seek(-1,2)
f.truncate() #Remove the last character, open the array
f.write(' , '.encode()) #Write the separator
f.write(json.dumps(_dict).encode()) #Dump the dictionary
f.write(']'.encode()) #Close the array
При редактировании файла вне скрипта следует соблюдать осторожность, чтобы в конце не добавлять пробелы.
Ответ 6
Вы никогда не пишете ничего, что связано с данными, которые вы читаете. Вы хотите добавить структуру данных в каналы к новой, которую вы создаете?
Или, возможно, вы хотите открыть файл в режиме добавления open(filename, 'a')
, а затем добавить свою строку, написав строку, созданную json.dumps
, вместо использования json.dump
, но nneonneo указывает, что это будет недействительным json.
Ответ 7
У меня есть некоторый код, который похож, но не переписывает все содержимое каждый раз. Это предназначено для периодического запуска и добавления записи JSON в конец массива.
Если файл еще не существует, он создает его и выгружает JSON в массив. Если файл уже создан, он доходит до конца, заменяет ]
на a ,
сбрасывает новый объект JSON, а затем снова закрывает его другим ]
# Append JSON object to output file JSON array
fname = "somefile.txt"
if os.path.isfile(fname):
# File exists
with open(fname, 'a+') as outfile:
outfile.seek(-1, os.SEEK_END)
outfile.truncate()
outfile.write(',')
json.dump(data_dict, outfile)
outfile.write(']')
else:
# Create file
with open(fname, 'w') as outfile:
array = []
array.append(data_dict)
json.dump(array, outfile)