我有两个嵌套的词典,我想要比较词典d1具有我从yaml文件中提取的所需值,而d2具有我从aws安全组获取的当前值。我想比较两个字典和显示
情景1 d2中存在的意外值,但d1中没有
情景2 并且还显示d1中但不在d2中的值。
我现在有以下代码
def CompareDict(d1, d2, ctx=""):
for k in d2:
if k not in d1:
continue
if d2[k] != d1[k]:
if type(d2[k]) not in (dict, list):
print k +" Expected Value "+str(d1[k])+" but found "+str(d2[k])
else:
if type(d1[k]) != type(d2[k]):
continue
else:
if type(d2[k]) == dict:
CompareDict(d1[k], d2[k], k)
continue
elif type(d2[k]) == list:
CompareDict(list_to_dict(d1[k]), list_to_dict(d2[k]), k)
return
当我的两个词典是 -
时,这适用于以下场景D2
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 99, u'FromPort': 0, u'IpRanges': [{u'CidrIp': '104.129.192.69/32'}], u'IpProtocol': 'udp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [], u'IpProtocol': 'tcp'}]}]}
D1
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': u'0.0.0.0/1'}], u'IpProtocol': u'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': u'0.0.0.0/32'}], u'IpProtocol': u'tcp'}]}]}
输出
ToPort预期值89但发现99
FromPort预期值80但找到0
CidrIp预期值0.0.0.0/1但发现104.129.192.69/32
IpProtocol期望值tcp但找到了udp
但是当我有两个字典
时,无法检查方案2- D2 ----
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [], u'IpProtocol': 'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [], u'IpProtocol': 'tcp'}]}]}
-D1 ---
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': u'0.0.0.0/1'}], u'IpProtocol': u'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': u'0.0.0.0/0'}], u'IpProtocol': u'tcp'}]}]}
输出
无
请有人帮忙。我是python的新手,非常感谢任何帮助
更新 -
场景3(未能检测到cidrIp值的变化,因为它在D2中为'0.0.0.0/0',在D1中为'0.0.0.0/1'。)
D2
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': '0.0.0.0/0'}], u'IpProtocol': 'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': '0.0.0.0/32'}], u'IpProtocol': 'tcp'}]}]}
D1
{u'SecurityGroups': [{u'IpPermissions': [{u'ToPort': 89, u'FromPort': 80, u'IpRanges': [{u'CidrIp': u'0.0.0.0/1'}], u'IpProtocol': u'tcp'}], u'IpPermissionsEgress': [{u'ToPort': 1, u'FromPort': 0, u'IpRanges': [{u'CidrIp': u'0.0.0.0/32'}], u'IpProtocol': u'tcp'}]}]}
输出:
答案 0 :(得分:0)
我认为这将满足您的一切需求。
import json
def compareIterables(d1, d2):
if [type(d1), type(d2)] == [dict,dict]:
notInD2 = set(d1.keys()) - set(d2.keys())
notInD1 = set(d2.keys()) - set(d1.keys())
inBoth = set(d2.keys()) & set(d1.keys())
for key in notInD2:
print "D2[{}] is not defined. Value in D1: {}".format(key, json,dumps(D1[key]))
for key in notInD1:
print "D1[{}] is not defined. Value in D2: {}".format(key, json,dumps(D2[key]))
elif [type(d1), type(d2)] == [list,list]:
len1 = len(d1)
len2 = len(d2)
if(len(d1) != len(d2)):
print "lists {} and {} do not have the same length!".format(d1,d2)
return
else:
inBoth = range(0,len1)
for key in inBoth:
if all([x not in [dict,list] for x in [type(d1[key]),type(d2[key])]]):
if type(d1[key]) == type(d2[key]):
if d1[key] != d2[key]:
print "d1[{0}] ({1}) does not match d2[{0}] ({2})".format(key, d1[key], d2[key])
else:
if([type(d1[key]),type(d2[key])] == [list,list]):
compareIterables(d1[key],d2[key])
elif([type(d1[key]),type(d2[key])] == [dict,dict]):
compareIterables(d1[key],d2[key])
elif type(d1[key]) != type(d2[key]):
print "type of d1[{0}] ({1}) does not match d2[{0}] ({2})".format(key, type(d1[key]), type(d2[key]))
这是您提供的第二对词典的输出。
lists [{u'CidrIp': u'0.0.0.0/1'}] and [] do not have the same length!
lists [{u'CidrIp': u'0.0.0.0/0'}] and [] do not have the same length!
您可以修改此脚本以递归方式传递密钥,以便更好地识别或使用您需要的任何其他功能。这只是一个基线。