打印Python词典的差异

时间:2012-10-18 14:27:28

标签: python

我想要两个词典并打印出它们的差异。此差异应包括键和值的差异。我已经创建了这个小片段,以使用unittest模块中的内置代码来实现结果。然而,这是一个讨厌的黑客,因为我必须继承unittest.TestCase并提供runtest()方法才能工作。此外,此代码将导致应用程序出错,因为当存在差异时它将引发AssertError。我真正想要的就是打印差异。

import unittest
class tmp(unittest.TestCase):
    def __init__(self):
         # Show full diff of objects (dicts could be HUGE and output truncated)
        self.maxDiff = None
    def runTest():
        pass
_ = tmp()
_.assertDictEqual(d1, d2)

我希望使用difflib模块,但它看起来只适用于字符串。有没有办法解决这个问题,仍然使用difflib

7 个答案:

答案 0 :(得分:5)

改编自cpython来源:

https://github.com/python/cpython/blob/01fd68752e2d2d0a5f90ae8944ca35df0a5ddeaa/Lib/unittest/case.py#L1091

import difflib
import pprint

def compare_dicts(d1, d2):
    return ('\n' + '\n'.join(difflib.ndiff(
                   pprint.pformat(d1).splitlines(),
                   pprint.pformat(d2).splitlines())))

答案 1 :(得分:2)

您可以使用difflib,但使用unittest方法似乎更适合我。但是如果你想使用difflib。让我们说以下是两个词。

In [50]: dict1
Out[50]: {1: True, 2: False}

In [51]: dict2
Out[51]: {1: False, 2: True}

您可能需要将它们转换为字符串(或字符串列表),然后将difflib用作正常业务。

In [43]: a = '\n'.join(['%s:%s' % (key, value) for (key, value) in sorted(dict1.items())])
In [44]: b = '\n'.join(['%s:%s' % (key, value) for (key, value) in sorted(dict2.items())])
In [45]: print a
1:True
2:False
In [46]: print b
1:False
2:True
In [47]: for diffs in difflib.unified_diff(a.splitlines(), b.splitlines(), fromfile='dict1', tofile='dict2'):
    print diffs

输出将是:

--- dict1

+++ dict2

@@ -1,2 +1,2 @@

-1:True
-2:False
+1:False
+2:True

答案 2 :(得分:1)

您可以使用.items()和集合来执行以下操作:

>>> d = dict((i,i) for i in range(10))
>>> d2 = dict((i,i) for i in range(1,11))
>>>
>>> set(d.items()) - set(d2.items())
set([(0, 0)])
>>>
>>> set(d2.items()) - set(d.items())
set([(10, 10)])
>>>
>>> set(d2.items()) ^ set(d.items())  #symmetric difference
set([(0, 0), (10, 10)])
>>> set(d2.items()).symmetric_difference(d.items())  #only need to actually create 1 set
set([(0, 0), (10, 10)])

答案 3 :(得分:1)

我发现了一个名为datadiff的库(没有很好的文档),它在python中给出了可散列数据结构的差异。你可以使用pip或easy_install安装它。试一试!

答案 4 :(得分:0)

Python recipe to create difference (as dictionary) of two dictionaries。你能描述一下输出应该是什么样的(请附上一个例子)吗?

答案 5 :(得分:0)

使用@ mgilson's solution并进一步说明OP请求使用unittest模块。

def test_dict_diff(self):
    dict_diff = list(set(self.dict_A.items()).symmetric_difference(set(self.dict_B.items()))))
    fail_message = "too many differences:\nThe differences:\n" +
                   "%s" % "\n".join(dict_diff)
    self.assertTrue((len(dict_diff) < self.maxDiff), fail_message)

答案 6 :(得分:0)

查看https://github.com/inveniosoftware/dictdiffer

print list(diff(
    {2014: [
        dict(month=6, category=None, sum=672.00),
        dict(month=6, category=1, sum=-8954.00),
        dict(month=7, category=None, sum=7475.17),
        dict(month=7, category=1, sum=-11745.00),
        dict(month=8, category=None, sum=-12140.00),
        dict(month=8, category=1, sum=-11812.00),
        dict(month=9, category=None, sum=-31719.41),
        dict(month=9, category=1, sum=-11663.00),
    ]},

    {2014: [
       dict(month=6, category=None, sum=672.00),
       dict(month=6, category=1, sum=-8954.00),
       dict(month=7, category=None, sum=7475.17),
       dict(month=7, category=1, sum=-11745.00),
       dict(month=8, category=None, sum=-12141.00),
       dict(month=8, category=1, sum=-11812.00),
       dict(month=9, category=None, sum=-31719.41),
       dict(month=9, category=1, sum=-11663.00),
    ]}))

给出了这个输出,我觉得非常棒:

[('change', ['2014', 4, 'sum'], (-12140.0, -12141.0))]

即。它给出了所发生的事情:一个价值&#34;改变了#34;路径&#34; [&#39; 2014&#39; 4,&#39; sum&#39;]&#34;并且它从-12140.0变为-12141.0。