如何比较字典,看看有什么变化?

时间:2016-01-18 09:46:41

标签: python dictionary

我的python代码中有3个词典:

  1. self.new_port_dict = {}#Dictionary用于存储新端口 来自curr_host
  2. self.old_port_dict = {}#Dictionary来存储来自old_host的旧端口
  3. self.results_ports_dict = {}#保存已更改/新添加端口的结果
  4. 脚本需要比较哪个端口发生了变化,我几乎无法提供帮助:

          def comp_ports(self,filename):
              try:
                    f = open(filename)
                    self.prev_report = pickle.load(f) # NmapReport
    
                    for s in self.prev_report.hosts:
                        self.old_port_dict[s.address] = set()
                        for x in s.get_open_ports():
                            self.old_port_dict[s.address].add(x)
    
                    for s in self.report.hosts:
                        self.new_port_dict[s.address] = set()
                        for x in s.get_open_ports():
                           self.new_port_dict[s.address].add(x)
    
                    print "The following Host/ports were available in old scan : !!"
                    print `self.old_port_dict`
                    print "--------------------------------------------------------"
                    print "The following Host/ports have been added in new scan:  !!"
                    print `self.new_port_dict`
                    for h in self.old_port_dict.keys():
                     self.results_ports_dict[h] = self.new_port_dict[h]- self.old_port_dict[h]
                     print "Result Change: for",h ,"->",self.results_ports_dict[h]         
    
     except Exception as l:
                 print l
    

    这将输出为:

    The following Host/ports were available in old scan : !!
    {'172.16.0.41': set([(80, 'tcp'), (666, 'tcp')]), '172.16.0.163': set([(80, 'tcp'), (22, 'tcp')])}
    --------------------------------------------------------
    The following Host/ports have been added in new scan:  !!
    {'172.16.0.41': set([(80, 'tcp'), (22, 'tcp')]), '172.16.0.163': set([(80, 'tcp'), (22, 'tcp')])}
    
    Result Change: for 172.16.0.41 -> set([(22, 'tcp')])  From set([(80, 'tcp'), (666, 'tcp')])
    
    Result Change: for 172.16.0.163 -> set([])  From set([(80, 'tcp'), (22, 'tcp')])
    

    正如你可以清楚地看到的那样,我也得到了改变后的字典。我想打印:

        For "host_name" , Port changed from "port_id" to "new_port_id" 
    
    ex: For 172.16.0.41, Port changed from (666, 'tcp')  to  (22, 'tcp')
    

3 个答案:

答案 0 :(得分:2)

根据Alex Martelli对Is there a better way to compare dictionary values

的回答

你可以这样做:

#eval the differences between the 2 dict:
diff_key=[key for key in old_port_dict if old_port_dict[key]!=new_port_dict[key]]
for key in diff_key:
    print "For %s, Port changed from %s to %s" %(key,old_port_dict[key],new_port_dict[key])

答案 1 :(得分:1)

我认为您不是在比较字典,而是与键对应的值。

这里的基本想法是:

  • 主机不能总是出现在过去和现在的扫描中,并且会使用collections.defaultdict,以确保即使在没有主机的情况下也可以直接比较值。因为缺少键的值将自动生成(空set

  • 端口set上有3个操作

    • &(十字路口):查看哪些端口在扫描中保持不变(相同端口)

    • old - new:查看哪些端口位于旧扫描中但不再位于新端口(已删除端口)

    • new - old:查看哪些端口在新扫描中但不在旧端口(添加端口)

有几种方法可以移动代码进行优化,但我想这一点要清晰得多。

希望有所帮助

import collections

scan0 = collections.defaultdict(set, {
    '172.16.0.41': set([(80, 'tcp'), (666, 'tcp')]),
    '172.16.0.163': set([(80, 'tcp'), (22, 'tcp')])
})

scan1 = collections.defaultdict(set, {
    '172.16.0.41': set([(80, 'tcp'), (22, 'tcp')]),
    '172.16.0.163': set([(80, 'tcp'), (22, 'tcp')])
})

hosts = sorted(set(scan0.keys() + scan1.keys()))


scan_same = dict()
scan_new = dict()
scan_del = dict()

for host in hosts:
    scan_same[host] = scan0[host] & scan1[host]
    scan_new[host] = scan1[host] - scan0[host]
    scan_del[host] = scan0[host] - scan1[host]

print()
print('-' * 10, 'Same')
for host, ports in scan_same.items():
    print(host, ':')
    for port in ports:
        print(':::', port[0], '/', port[1])
print()
print('*' * 10, 'Added')
for host, ports in scan_new.items():
    print(host, ':')
    for port in ports:
        print(':::', port[0], '/', port[1])

print()
print('=' * 10, 'Deleted')
for host, ports in scan_del.items():
    print(host, ':')
    for port in ports:
        print(':::', port[0], '/', port[1])

这将输出:

---------- Same
172.16.0.163 :
::: 80 / tcp
::: 22 / tcp
172.16.0.41 :
::: 80 / tcp

*********** Added
172.16.0.163 :
172.16.0.41 :
::: 22 / tcp

========== Deleted
172.16.0.163 :
172.16.0.41 :
::: 666 / tcp

答案 2 :(得分:0)

您需要保留old_port_dict_changed = self.old_port_dict[h] - self.new_port_dict[h]之类的其他设置,现在old_port_dict中已更改的端口位于old_port_dict_changed,而替换旧端口的新端口位于results_ports_dict。这有帮助吗?