Normal python dictionaries allow a single value for a given key. However, a default dictionary allows a list as values, which solves the problem of non-unique keys.
An example which is not allowed in python.
vodka: gray, vodka: blue, vodka: red
Let’s look how we can deal with this using defaultdict.
from collections import defaultdict
myconfigstring = ('interface fa0/0, ip address 192.168.0.2 255.255.255.0, shutdown, desc LAN\ninterface fa0/1, ip address 192.168.1.2 255.255.255.0, shutdown, desc WAN')
data_list = [lines.split(",") for lines in myconfigstring.split("\n")]
full_dict = defaultdict(list)
for line in data_list:
print(line)
interface = line[0]
ipaddress = line[1]
state = line[2]
desc = line[3]
interfacedetails = (ipaddress, state, desc)
full_dict[interface].append(interfacedetails)
print(full_dict)
This produces:
defaultdict(, {'interface fa0/0': [(' ip address 192.168.0.2 255.255.255.0', ' shutdown', ' desc LAN')], 'interface fa0/1': [(' ip address 192.168.1.2 255.255.255.0', ' shutdown', ' desc WAN')]})
However, this is not a nested one yet, because we might want to have a dict like this:
{alcohols: {vodkas: {red, blue, green}, beers: {strong, weak}}}
Let’s now look at how we can use this to populate a router configuration block.
my_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))
my_dict['R1']['interface fa0/0']['ip address'] = '192.168.0.1 255.255.255.0'
my_dict['R1']['interface fa0/0']['desc'] = 'LAN'
my_dict['R2']['interface loop0/0']['ip address'] = '2.2.2.2 255.255.255.0'
This produces the desired result:
{"R1": {"interface fa0/0": {"ip address": "192.168.0.1 255.255.255.0", "desc": "LAN"}}, "R2": {"interface loop0/0": {"ip address": "2.2.2.2 255.255.255.0"}}}
Where do we go from here?
Now it’s time to rewrite our configuration change file and rewrite the method to create and populate the dictionary from that input file.
This is the original form of my method.
def makedictionaryfromchangefile():
#looping through list of configs and parsing the config
with open('change.txt', 'r') as reader:
configchangetext = reader.read()
stext = configchangetext.split('\n')
mydict = dict(map(lambda s: s.split(','), stext))
Dict = { }
for k, v in mydict.items():
v = dict(z.split(";") for z in v.split("?"))
Dict[k] = {}
y = 0
for y in range(y,len(v)):
eachitem = list(v.items())[y]
Dict[k][eachitem[0]] = eachitem[1]
return Dict
to be continued in Implementing idempotency in Unicon a.k.a do the desired changes already exist on the router? Part 3, Rewriting the dictionary