Python: добавление элемента в список файлов без чтения и записи каждый раз [duplicate]

Я абсолютно предпочитаю идею Джеффа Йетса. Он будет работать отлично, если вы слегка измените его:

  string regex = String.Format ("[{0}]", Regex.Escape (новая строка (Path.GetInvalidFileNameChars ()))  );  Regex removeInvalidChars = new Regex (regex, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.CultureInvariant);   

Улучшение заключается в том, чтобы избежать автоматического создания регулярного выражения.

22
задан Schiphol 21 October 2012 в 04:29
поделиться

6 ответов

Вероятно, вы хотите использовать JSON list вместо словаря в качестве элемента верхнего уровня.

Итак, инициализируйте файл пустым списком:

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. Если вы вызываете его в цикле, подумайте о том, чтобы добавить все каналы в список заранее, а затем записать список за один раз.

26
ответ дан nneonneo 16 August 2018 в 00:41
поделиться
  • 1
    Благодарю. feeds не указан в вашем примере кода. Должен ли он быть json.dump исходного файла? Это то, что я пытался, и это, похоже, не работает. – Schiphol 21 October 2012 в 11:07
  • 2
    Сожалею. Он предназначен для замены только блока записи в вашем оригинале add. – nneonneo 21 October 2012 в 17:17
  • 3
    Когда вы начинаете файл с with open(DATA_FILENAME, mode='r', encoding='utf-8') as f: json.dump([], f), вы хотите использовать with open(DATA_FILENAME, mode='w', encoding='utf-8') as f: json.dump([], f) вместо этого, чтобы открыть файл для записи, вместо чтения (если файл не существует, его нельзя прочитать). – Blairg23 5 November 2015 в 13:56
  • 4
    Упс, исправлено. Благодарю. – nneonneo 5 November 2015 в 17:16

Использование a вместо w должно позволить вам обновить файл вместо создания нового / перезаписать все в существующем файле.

См. этот ответ для разница в режимах.

4
ответ дан Community 16 August 2018 в 00:41
поделиться
  • 1
    КРАСИВАЯ! просто нужно «а» вместо «w». ничего сумасшедшего – Paul Paczuski 25 October 2017 в 19:22
  • 2
    Это не работает для меня. Он просто объединяет два разных списка, аннулируя json. Это выглядит так: [data1, data2, ..., dataN][dataN+1, dataN+2, ...] – Eduardo Pignatelli 4 April 2018 в 09:37
  • 3
    Это просто добавляется к файлу , а не к массиву внутри файла. – Milan Velebit 30 April 2018 в 11:24

Одно из возможных решений - выполнить конкатенацию вручную, вот какой-то полезный код:

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

Вы должны быть осторожны при редактировании файла вне сценария, не добавляя никакого промежутка в конце.

2
ответ дан SEDaradji 16 August 2018 в 00:41
поделиться
  • 1
    К сожалению, он больше не будет работать в Python 3.2+, если не в двоичном режиме, так как вам нужно указать кодировку. Следующий вопрос stackoverflow дает некоторый намек: stackoverflow.com/questions/18857352/… – Brown nightingale 23 January 2018 в 01:03
  • 2
    Вы правы, я отредактирую код – SEDaradji 16 June 2018 в 10:02

json не может быть лучшим выбором для форматов на диске; Проблема, связанная с добавлением данных, является хорошим примером того, почему это может быть. В частности, объекты json имеют синтаксис, который означает, что весь объект должен быть прочитан и проанализирован, чтобы понять любую его часть.

К счастью, есть много других вариантов. Особенно простой - CSV; который хорошо поддерживается стандартной библиотекой python. Самым большим недостатком является то, что он хорошо работает только для текста; он требует дополнительных действий со стороны программиста для преобразования значений в числа или другие форматы, если это необходимо.

Другой вариант, который не имеет этого ограничения, заключается в использовании базы данных sqlite, которая также имеет встроенную базу данных, в поддержке в python. Это, вероятно, будет большим отступлением от кода, который у вас уже есть, но он более естественно поддерживает модель «изменить немного», которую вы, по-видимому, пытаетесь построить.

26
ответ дан SingleNegationElimination 16 August 2018 в 00:41
поделиться
  • 1
    Благодарю. Я пытаюсь закодировать небольшой агрегатор подкастов. Не является ли база данных sqlite немного избыточной для того, что может быть 8-10 строк данных фида? – Schiphol 21 October 2012 в 04:13
  • 2
    правильным инструментом для задания является never overkill. – SingleNegationElimination 21 October 2012 в 04:31
  • 3
    Если ваши данные единообразны, вы можете добавить их в json-подобный файл, просто каждая строка содержит нужный объект. Затем, когда вы читаете, просто анализируйте каждую строку как объект json. – Jonno_FTW 18 August 2017 в 05:22
  • 4
    @Jonno_FTW: использование файла в этом формате было бы немного более трудным, чем sqlite; В первом случае вам нужно аккумулировать все объекты в полезную структуру. Хотя это всего лишь полдюжины строк python, это все равно около полутора десятков больше, чем одна строка, необходимая для работы с sqlite или CSV. – SingleNegationElimination 18 August 2017 в 12:01
  • 5
    @SingleNegationElimination предполагает, что ваши данные единообразны и хорошо вписываются в таблицу SQL. Кроме того, с json вы получаете больше типов, чем строки CSV. Кроме того, вы можете загрузить все с помощью [json.loads(i) for i in open('somefile.json','r').readlines()] – Jonno_FTW 24 August 2017 в 01:20

Вы никогда не пишете ничего, что связано с данными, которые вы читаете. Хотите добавить структуру данных в каналы к новой, которую вы создаете?

Или, возможно, вы хотите для открытия файла в режиме добавления open(filename, 'a'), а затем добавьте свою строку, написав строку, созданную json.dumps, вместо использования json.dump, но nneonneo указывает, что это будет недействительным json.

1
ответ дан Thomas 16 August 2018 в 00:41
поделиться
  • 1
    Это хорошая попытка, но он собирается записать недопустимый JSON в файл (например, {"a":"b"}{"c":"d"}). – nneonneo 21 October 2012 в 03:41
  • 2
    Да, я хотел добавить структуру данных в фидах к той, которую создаю. Позвольте мне изменить вопрос, чтобы это было ясно. – Schiphol 21 October 2012 в 03:47

Добавить запись в содержимое файла, если файл существует, в противном случае добавить запись в пустой список и записать в файл:

a = []
if not os.path.isfile(fname):
    a.append(entry)
    with open(fname, mode='w') as f:
        f.write(json.dumps(entry, 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))
7
ответ дан timgeb 16 August 2018 в 00:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: