Print diff of Python dictionaries
我想拿两本字典,把它们打印出来。这个差异应该包括键和值之间的差异。我创建了这个小片段,以使用
1 2 3 4 5 6 7 8 9 | 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) |
我希望使用
改编自cpython来源:
https://github.com/python/cpython/blob/01fd68752e2d0a5f90ae8944ca35df0a5deaa/lib/unittest/case.py l1091
1 2 3 4 5 6 7 8 9 | import difflib import pprint def compare_dicts(d1, d2): return (' ' + ' '.join(difflib.ndiff( pprint.pformat(d1).splitlines(), pprint.pformat(d2).splitlines()))) |
你可以使用difflib,但是使用unittest方法对我来说更合适。但如果你想使用difflib。假设下面是两个听写。
1 2 3 4 5 | In [50]: dict1 Out[50]: {1: True, 2: False} In [51]: dict2 Out[51]: {1: False, 2: True} |
号
您可能需要将它们转换为字符串(或字符串列表),然后将difflib用作正常业务。
1 2 3 4 5 6 7 8 9 10 11 12 | In [43]: a = ' '.join(['%s:%s' % (key, value) for (key, value) in sorted(dict1.items())]) In [44]: b = ' '.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 |
输出将是:
1 2 3 4 5 6 7 8 9 10 | --- dict1 +++ dict2 @@ -1,2 +1,2 @@ -1:True -2:False +1:False +2:True |
。
我发现了一个名为datadiff的库(没有很好的文档记录),它给出了python中散列数据结构的不同之处。您可以使用pip或easy-install安装它。试试看!
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> 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)]) |
查看https://github.com/inveniosoftware/dictdiffer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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), ]})) |
。
给出了我认为非常好的输出:
1 | [('change', ['2014', 4, 'sum'], (-12140.0, -12141.0))] |
。
也就是说,它给出了发生的事情:一个值"已更改",路径"['2014',4,'sum']",它从-12140.0更改为-12141.0。
使用@mgilson的解决方案,并进一步满足OP使用
1 2 3 4 5 6 7 8 | 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: The differences: " + "%s" %" ".join(dict_diff) self.assertTrue((len(dict_diff) < self.maxDiff), fail_message) |
请参阅python配方以创建两个字典的差异(作为字典)。你能描述一下输出应该是什么样子吗(请附上一个例子)?