2017-09-14 46 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()來處理腳本中的所有內容,我將在後面介紹這些內容,然後將「','',''添加到末尾的列定義。它修復了錯誤並且輸出是完美的。非常感謝你的幫助,我非常感謝! –