2014-01-25 7 views
2

Мне нужна помощь, пытаясь использовать difflib для сравнения двух dicts. Моя программа принимает 2 файла json, преобразует их в python dicts. Затем я хотел бы использовать difflib для двух dicts, чтобы отобразить различия между ними.difflib сравнить два словаря python

Каков правильный способ использования difflib для этого?

#!/usr/bin/env python2 

import json 
import collections 
import difflib 
import pprint 

def get_json(): 
    file_name = raw_input("Enter name of JSON File: ") 
    with open(file_name) as json_file: 
     json_data = json.load(json_file) 
     return json_data 

def convert(data): 
    if isinstance(data, basestring): 
     return str(data) 
    elif isinstance(data, collections.Mapping): 
     return dict(map(convert, data.iteritems())) 
    elif isinstance(data, collections.Iterable): 
     return type(data)(map(convert, data)) 
    else: 
     return data 

def main(): 
    json1 = get_json() 
    json2 = get_json() 
    json1_dict = convert(json1) 
    json2_dict = convert(json2) 
    result = list(difflib.Differ.compare(json1_dict, json2_dict)) 
    pprint.pprint(result) 

if __name__ == "__main__": 
    main() 

JSON Пример:

{ 
    "glossary": { 
     "title": "example glossary", 
     "GlossDiv": { 
      "title": "S", 
      "GlossList": { 
       "GlossEntry": { 
        "ID": "SGML", 
        "SortAs": "SGML", 
        "GlossTerm": "Standard Generalized Markup Language", 
        "Acronym": "SGML", 
        "Abbrev": "ISO 8879:1986", 
        "GlossDef": { 
         "para": "A meta-markup language, used to create markup languages such as DocBook.", 
         "GlossSeeAlso": [ 
          "GML", 
          "XML" 
         ] 
        }, 
        "GlossSee": "markup" 
       } 
      } 
     } 
    } 
} 

И изменить значение ID в «1234» во втором файле

Я хотел сравнить два и получить и выход что-то вроде:

{ 
    "glossary": { 
     "title": "example glossary", 
     "GlossDiv": { 
      "title": "S", 
      "GlossList": { 
       "GlossEntry": { 
-     "ID": "SGML", 
+     "ID": "1234", 
        "SortAs": "SGML", 
        "GlossTerm": "Standard Generalized Markup Language", 
        "Acronym": "SGML", 
        "Abbrev": "ISO 8879:1986", 
        "GlossDef": { 
         "para": "A meta-markup language, used to create markup languages such as DocBook.", 
         "GlossSeeAlso": [ 
          "GML", 
          "XML" 
         ] 
        }, 
        "GlossSee": "markup" 
       } 
      } 
     } 
    } 
} 
+0

'Differ.compare' - это метод экземпляра. Есть ли какая-то цель для вашей функции 'convert', кроме как избавиться от строк unicode? Во всяком случае, 'difflib' работает над последовательностями строк, а не на любых объектах, таких как словари. Какой контент у ваших json-файлов? Что вы ожидаете от вывода вашей программы? – Blckknght

+0

Я не думаю, что это то, для чего нужен difflib; он предназначен для создания различий между текстовыми файлами. Какова структура ваших файлов JSON? Являются ли они только 2 уровня (или так), или вам потребуется рекурсивное решение? – dstromberg

+0

Функция преобразования только для того, чтобы избавиться от юникода, есть ли лучший способ сделать это? Я отредактирую вопрос с примерами json-файлов и ожидаемого вывода. – user3230554

ответ

1

У вас есть несколько вопросов здесь. Во-первых, вы пытаетесь использовать метод difflib.Differ.compare, но вы называете его простой функцией - вы на самом деле не создали объект difflib.Differ.

Во-вторых, этот метод compare предполагает, что вы будете работать с последовательностью строк (для сравнения каждой из двух вещей). Ваша функция convert иногда возвращает строки, иногда дикты, иногда другие вещи ... в общем, вы не возвращаете последовательности строк.

Естественный способ получить то, что вы хотите, это просто сравнить фактические данные JSON, потому что это строка. Тем не менее, есть два вопроса, есть:

  • вы хотите последовательность строк (строка за строкой) вместо одной строки со всем документом JSON, но это тривиально - просто разбить его на строки с строка .splitlines способ.

  • Ваш вход может иметь отличия в пробеле, которые вы хотите игнорировать. Простой способ это сделать после load ввода каждого документа JSON в объект, заново создать для него строку с dumps. Идея заключается в том, что для обоих документов, которые вы сравниваете, вы сбросите с теми же настройками пробелов. Вам необходимо прочитать документацию и решить, какие настройки вы хотите использовать.

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