2017-09-14 42 views
0

我正在写一个python脚本,它可以解析包含所有配置信息,模型,软件类型,软件版本等等的1000个Rancid文件,网络。到目前为止,我已经得到它正确循环所有的文件,并通过主机名,软件类型(IE IOS,IOS XR,JUNOSE,JUNOS等)的路由器打印出好的列表路由器,以及什么软件版本是(IE 12.3R7,15.2(2)T1,12.1.1p0.1等)。Python动态字典,多值每键计数

问题是,由于在任何时候网络团队都可以添加新的路由器型号,将软件升级到未知版本或者其他类型,通过为每个单一路由器类型,软件版本添加变量来管理它等等,都需要对脚本进行持续的维护,我不愿意这么做,所以我使所有的变量都是动态的。它循环遍历文件,找到适当的软件类型,版本和型号(因为每个供应商通常不会更改从版本到版本的呈现方式)。然后将该变量分配为'模型','类型'和'版本',然后将其打印出来。

我想能够添加一个argparse到我的代码,以便在需要时而不是打印整个列表时,我可以得到一个带有计数的摘要,所以在循环的每次传递过程中,我都会添加它的值找到每个关键字典的多值。

以下是字典的构建方式以及打印方式。

我设置的关键文件名是基于关闭主机名(这样的分析较少有关更多信息,原始数据)

key = file 
mydict.setdefault(key, []) 
mydict[key].append(model) 
mydict[key].append(type) 
mydict[key].append(version) 

#here is an example of what the dictionary looks like 
print mydict 

{'router1': ['model1', 'JUNOS', '12.3R7'], 'router2': ['model1', 'JUNOS', 
'13.3R4'], 'router3': ['model2', 'IOS', '15.2'], 'router4': ['model3', 
'JUNOS', '11.4R1'], 'router5': ['model2', 'IOS', '15.3'], 'router6': 
['model4', 'JUNOSe', '12.1.1p0.1'], 'router7': ['model1', 'JUNOS', 
'12.3R7'], 'router7': ['model1', 'JUNOS', '12.3R7'], 'router8': ['model1', 
'JUNOS', '13.3R4'], 'router9': ['model2', 'IOS', '15.2'], 'router10': 
['model3', 'JUNOS', '11.4R1'], 'router11': ['model2', 'IOS', '15.3'], 
'router12': ['model5', 'JUNOS', '12.3R7']} 

我想是一种方法来匹配所有副本,所有3值是相同的,算来,然后打印出来在这样一个很好的格式化列表(忽略的关键,因为它打印为这项工作并不重要)

JUNOS model1 12.3R7 3 
JUNOS model1 13.3R4 2 
JUNOS model3 11.4R1 2 
JUNOS model5 12.3R7 1 
IOS  model2 15.2 2 
IOS  model2 15.3 2 
JUNOSE model4 12.1.1p0.1 1 

甚至更​​优选(但可能更难)将是

JUNOS 

model1 12.3R7 2 
     13.3R4 2 
model3 11.4R1 2 
model5 12.3R7 1 

JUNOSE 

model2 12.1.1p0.1 1 

IOS 

model2 15.2 2 
     15.3 2 

回答

0

也许大熊猫库可以帮助您实现这一目标:https://pandas.pydata.org/index.html
可以mydict转换为大熊猫据帧,然后使用GROUPBY()方法来获取所有组。最后用大小()来计数。

你可以这样做:

import pandas as pd 
mydict = {} #your dict here 
df = pd.DataFrame.from_dict(mydict,'index') 
df.columns=['model','type','version'] #Affect column names to your DF. 
print(df.groupby(['type','model','version']).size()) 

这就给了你:

type model version 
IOS  model2 15.2   2 
       15.3   2 
JUNOS model1 12.3R7  2 
       13.3R4  2 
     model3 11.4R1  2 
     model5 12.3R7  1 
JUNOSe model4 12.1.1p0.1 1 

当你与df.columns=...影响的列名,确保它适合你的字典值。您必须具有与值列表长度一样多的列。

GROUPBY然后大小可以在这里找到的其他例子:Duplicate rows in pandas DF

编辑 - 快译通结构化
在我看来,这应该是用字典为值的更具描述性的字典更好而不是列表,如:

{'router1': {'bar': None, 
    'foo': None, 
    'model': 'model1', 
    'type': 'JUNOS', 
    'version': '12.3R7'}, 
'router2': {'bar': None, 
    'foo': None, 
    'model': 'model1', 
    'type': 'JUNOS', 
    'version': '13.3R4'},...} 

这样pd.DataFrame.for m_dict会自动影响列名称。上面的代码将是:

import pandas as pd 
mydict = {} #your dict of dicts here 
df = pd.DataFrame.from_dict(mydict,'index') 
print(df.groupby(['type','model','version']).size()) 
+0

这看起来解决这个问题的好办法,但与功能的麻烦: 回溯(最近通话最后一个): 文件“software-versions.py”,行111 in df.columns = ['model','type','version'] ..... <大量调用python文件的路径> .... ValueError:长度不匹配:期望轴有6个元素,新值有3个元素 不确定是什么导致了这个错误。根本就没有与panads库合作过,所以我不确定这个轴和元素是如何工作的。 –

+0

你的字典有改变吗?在你的例子中,每个键(路由器)都有一个三个值列表('model','type','version')。确保标记每一列。例如,如果您的字典包含像('模型','类型','版本','foo','bar')的值,请执行:df.columns = ['model','type','version','富”, '酒吧']。 –

+0

我相信当值被放入字典时,它可能会得到不可见的东西,比如/ n/s/t或类似的东西,这些东西会被计算为附加列。 因此,我并没有通过并剥离(),lstrip()或rstrip()来处理脚本中的所有内容,我将在后面介绍这些内容,然后将“','',''添加到末尾的列定义。它修复了错误并且输出是完美的。非常感谢你的帮助,我非常感谢! –