使用difflib比较两个Python字典

3

我需要帮助,尝试使用difflib比较两个字典。我的程序采用2个json文件,将其转换为python字典。然后,我想使用difflib在这两个字典上显示差异。

正确使用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"
                }
            }
        }
    }
}

Differ.compare是一个实例方法。你的convert函数除了去掉Unicode字符串外还有其他用途吗?无论如何,difflib只能处理行序列,而不能处理像字典这样的任意对象。你的JSON文件中包含什么样的内容?你希望程序的输出是什么样子的? - Blckknght
我认为这不是difflib的用途;它是用于生成文本文件之间的差异。你的JSON文件结构是什么样子的?它们只有两个层级(左右)深度,还是需要递归解决方案? - dstromberg
转换函数只是为了摆脱Unicode,有更好的方法吗?我将编辑问题,并附上JSON文件和预期输出的示例。 - user3230554
@Blckknght,convert函数只是为了去掉Unicode,有更好的方法吗?我已经编辑了问题,并附上了JSON文件和预期输出的示例。 - user3230554
@dstromberg,那么difflib对我来说不是正确的方法,您有什么建议可以让我得到所需的输出吗? - user3230554
1个回答

2
你有一些问题。首先,你尝试使用 方法 difflib.Differ.compare,但你把它当作普通函数调用了 - 实际上你并没有创建一个 difflib.Differ 对象

其次,这个 compare 方法期望你对一系列字符串进行操作(对于要比较的两个东西中的每一个)。你的 convert 函数有时返回字符串,有时返回字典,有时返回其他东西...总的来说,你没有得到字符串序列。

得到你想要的自然方式就是比较实际的 JSON 数据,因为那是一个字符串。然而,这里有两个问题:

  • 您想要一个字符串序列(逐行)而不是整个JSON文档的单个字符串,但这很简单-只需使用字符串.splitlines方法将其拆分成行。

  • 您的输入可能具有您想要忽略的空格差异。解决这个简单的方法是,在将每个JSON文档加载到对象中后,使用dumps重新创建一个字符串。思路是对于您要比较的两个文档,您将使用相同的空格设置进行转储。您需要阅读文档并决定要使用哪些设置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接