2013-09-17 3 views
-1

Прошу прощения за код на испанском языке, но кроме того, вы должны понимать его структуру, я использую Python 3.3.2 и получаю здесь проблему.python Как обновить список json, если условие соответствует

leyendoestadisticas = open("listas\Estadisticas.txt", "r") 
bufferestadisticas = leyendoestadisticas.read() 
leyendoestadisticas.close() 
if not '"'+user.name+'"' in bufferestadisticas: #If name is not found, do this 
    escribiendoestadisticas = open("listas\Estadisticas.txt", 'a') 
    escribiendoestadisticas.write(json.dumps([user.name, palabrasdelafrase, letrasdelafrase, 
              "1", user.nameColor, user.fontColor, user.fontFace, user.fontSize, message.body, room.name])+"\n") 
    escribiendoestadisticas.close() 
else: #If name is found... 
    data = [] 
    with open('listas\Estadisticas.txt', 'r+') as f: 
    for line in f: 
     data_line = json.loads(line) 
     if data_line[0] == user.name: #if name matches... 
     if data_line[9] == room.name: #And room also, then update info. 
      data_line[1] = int(data_line[1])+int(palabrasdelafrase) 
      data_line[2] = int(data_line[2])+int(letrasdelafrase) 
      data_line[3] = int(data_line[3])+1 
      data_line[4] = user.nameColor 
      data_line[5] = user.fontColor 
      data_line[6] = user.fontFace 
      data_line[7] = user.fontSize 
      data_line[8] = message.body 
      data_line[9] = room.name 
     else: #but if name is found and room doesn't matches. #PROBLEM HERE 
      escribiendoestadisticas = open("listas\Estadisticas.txt", 'a') 
      escribiendoestadisticas.write(json.dumps([user.name, palabrasdelafrase, letrasdelafrase, 
                "1", user.nameColor, user.fontColor, user.fontFace, user.fontSize, message.body, room.name])+"\n") 
      escribiendoestadisticas.close() 
     data.append(data_line) 
     break 
    f.seek(0) 
    f.writelines(["%s\n" % json.dumps(i) for i in data]) 
    f.truncate() 

Это цель состоит в том, чтобы добавить user.name и обновлять это информация, пока свойство 9 линии соответствует. Если нет совпадений, добавьте новую строку в список с тем же именем user.name, но новое значение для свойства 9.

Это работает отлично, если свойство 9 соответствует, однако, если это не так, то что он делает, для переопределения существующего значения этого user.name и начала подсчета свойств в [1], [2] и [3] с нуля.

Спасибо за помощь.

EDIT: Обновление с информацией из ответа:

else: 
    data = [] 
    with open('listas\Estadisticas.txt', 'r+') as f: 
    lines = f.readlines() 
    for line in lines: 
    data_line = json.loads(line) 
    if data_line[0] == user.name: 
     if data_line[9] == room.name: 
     data_line[1] = int(data_line[1])+int(palabrasdelafrase) 
     data_line[2] = int(data_line[2])+int(letrasdelafrase) 
     data_line[3] = int(data_line[3])+1 
     data_line[4] = user.nameColor 
     data_line[5] = user.fontColor 
     data_line[6] = user.fontFace 
     data_line[7] = user.fontSize 
     data_line[8] = message.body 
     data_line[9] = room.name 
     data.append(data_line) 
    f.seek(0) 
    f.writelines(["%s\n" % json.dumps(i) for i in data]) 
    f.truncate() 
    for line in lines: 
    data_line = json.loads(line) 
    if data_line[0] == user.name: 
     if not data_line[9] == room.name: 
     escribiendoestadisticas = open("listas\Estadisticas.txt", 'a') 
     escribiendoestadisticas.write(json.dumps([user.name, palabrasdelafrase, letrasdelafrase, 
               "1", user.nameColor, user.fontColor, user.fontFace, user.fontSize, message.body, room.name])+"\n") 
     escribiendoestadisticas.close() 

Но теперь я получаю сообщение об ошибке: ValueError: операции ввода/вывода в закрытом файле. Полностью потерян.

+2

http://www.python.org/dev/peps/pep-0008/#indentation –

+0

вы хотите добавить в файл на лету, или переписать все это в конце концов делать? Вы, конечно, не можете делать _both_. – abarnert

+1

Я не уверен, имеет ли смысл самое внутреннее условие 'else'. Если имя пользователя может быть в файле несколько раз с разными номерами комнат, вы, вероятно, захотите выполнить поиск по всему файлу, пока не найдете подходящую комнату, вместо того, чтобы ломаться после поиска первого совпадающего имени. – Blckknght

ответ

0

Похоже, вы изменяете файл, сохраняя при этом его чтение. Загрузите файл полностью первым, и пусть обработчик контекста закрыть файл:

else: #Si está, suma datos 
    data = [] 
    with open('listas\Estadisticas.txt', 'r+') as f: 
     lines = f.readlines() 

    for line in lines: 
    data_line = json.loads(line) 
    if data_line[0] == user.name: #if name is found... 
     if data_line[9] == room.name: #And room also, then update info. 
     data_line[1] = int(data_line[1])+int(palabrasdelafrase) 
     [etc] 

Как и другие люди указали в комментариях, вы, вероятно, хотите найти весь файл для user.name, а не только линия за линией в любом случае.

Кроме того, как указывает @abarnert, достаточно просто изменить data в своих циклах, а затем выписать полный комплект информации в конце.


Несколько общих замечаний:

  • Ваш код не обрабатывает случай, когда data_line содержит менее 10 пунктов. Если это произойдет, ваша программа выйдет из строя.

  • Вам будет гораздо лучше с помощью json, чтобы сэкономить dict. Таким образом, при загрузке dict вы можете немедленно проверить и получить доступ к user.name. Я предлагаю вам сделать user.name ключом словаря.

Это может выглядеть примерно так (EDIT: видел, как вы хотели, уникальные комбо user.name и room.name):

with open('listas\Estadisticas.json', 'rb') as f: 
    data = json.load(f) 

key = (user.name, room.name) 

if key in data: 
    data[key]['nameColor'] = user.nameColor 
    [...etc...] 
else: 
    # I am not sure what details are different 
    data[key] = {} # New sub-dict 
    data[key]['nameColor'] = user.nameColor 
    [...etc...] 

with open('listas\Estadisticas.json', 'wb') as f: 
    json.dump(f, data) 
  • имен может изменить. Вот почему базы данных обычно используют ключи, которые не являются именами людей или именами комнат. Я бы предположил, что вы присваиваете имена вещей чему-то еще абстрактному, например номерам, а затем просматриваете имена, когда это необходимо для отображения. Если имя пользователя неправильно вводится неправильно, а затем они хотят исправить написание имени, вам будет сложно объяснить им, что вы не можете, потому что это будет означать, что все их данные будут потеряны ...
+0

Хотя я понимаю, что вы оба хотели сказать, я боюсь, что я слишком noob, чтобы искать во всем файле для имени пользователя без метода линии за строкой json-модуля. Поэтому я просто пытался сделать обходной путь. – Saelyth

+0

Никогда не использовал dicts раньше, но если я правильно понимаю этот код, где вы говорите, что имя комнаты - это значение 9 в списке? – Saelyth

+0

Итак, мои данные не являются списком. Это словарь с ключом. Ключ - это кортеж с двумя записями: 'user.name' и' room.name'. Если пользователю еще не назначена комната, то кортеж просто выглядит как '(user.name," ")'. Настройка этого способа облегчает поиск пользователей и предотвращает дублирование комбинации пользователя и комнаты. –

Смежные вопросы