Python Forum
Getting list inside of a list; how to clean it and retrieve value
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Getting list inside of a list; how to clean it and retrieve value
#1
When I print output from a dictionary, I get the following output as shown under "NOW LISTING".
to be honest I cannot understand at what point the data got these multiple [[[. It seems a list inside of a list but I do not know why.

Question: based on this, how would you retrieve value thru this data structure? Or should I fix the origin of these behavior? I am pasting code below.
******************* NOW LISTING ***********************
defaultdict(<class 'list'>, {'PSE2': ['0/7/CPU0', '1/0/CPU0', '1/2/CPU0'], 'IF_PSE1': [['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'IF_PSE2': [['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'NODE': [[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]})


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
import paramiko
import copy
import os
import sys
import re
import getpass
import time
import json
from collections import defaultdict
 
#User and Password is Cisco CEC
USERNAME = 'admin'
TARGET_SERVER = '10.1.1.1'
TOLERANCE = 400
MGROUP = "224.0.0.0/24"
 
def olist(raw_show_data):
    #Separate the output for the respective show commands executed
    olist_data  = raw_show_data.split('#show')
    #Separate data from 3 show commands given (show mrib route, show mfib route rate, show platform)
    #print(olist_data[1])
    #print(olist_data[2])
    #print(olist_data[3])
    #==>delete this:using bogus data for now
    olist_data[1] = """TenGigE0/5/0/1.999 Flags: Outgoing Interface List  TenGigE0/5/0/21.201 Flags: F NS, Up: 01:06:23 TenGigE0/7/0/3.1  >>> CRS-X interface ( 1st PSE)"""
     
    #1) Analyze 'show platform' and determine if it is 1 PSE or 2 PSE architecture
     
    var_dict = {}
    show_platform_str  = olist_data[3].strip()
    show_platform_list = show_platform_str.split('\n')
    #Create a dictionary to organize all Nodes which are PSE-2 architecture. Dictionary if_dic will contain list of outgoing interfaces(o-list) which are on PSE2 or PSE1
    var_dict = defaultdict(list)
    for element in show_platform_list:
        match =re.findall(r'(FP-X|MSC-X|SPC-X)',element)
 
        if match:
            #The first element on each line is the Node#:
            break_element = element.split(' ')
            #Build a list of all Node# which are PSE2          
            var_dict['PSE2'].append(break_element[0])
 
 
    #2)Analyze the outgoing interfaces on show mrib route
    #Only consider outgoing interface lists (o-list):
    #A dict to organize interface status
    olist_dic = {}
    raw_int_data = olist_data[1].split('Outgoing Interface List')
    raw_int_out  = raw_int_data[1]
     
    #Get list of interfaces
    match_int  = re.findall(r'(TenGig[A-Za-z0-9\/\.]+)', raw_int_out)
    if match_int:
 
       for entry in match_int:
            raw_int_ids = entry.split('/')
            #Get the interface port ID
            raw_portids = raw_int_ids[3].partition(".")
            port_id = raw_portids[0]
             
            #Get the interface  CPU/Node position
            port_cpu_pos = (raw_int_ids[0]+"/"+raw_int_ids[1])
            match = re.findall(r'(\d\/\d)',port_cpu_pos)
             
            #Copy dictinary so that  I can interate and modify the original one.
            temp_var_dict = var_dict.copy()
             
            for k, v in temp_var_dict.items():
                           match = str(match)
                           match = match.strip("[]")
                           match = match.strip("''")
                           result = [index for index, value in enumerate(v) if match in value]
                           result = str(result)
                           result = result.strip("[]")
                           result = result.strip("'")
                           #====> IF I print(var_dict), at this point I have no error ********* 
                           if result == "0":
                               #It means a match between interface on  RP PSE2 model was found; Interface position is on PSE2 architecture
                               print (f'PSE-2 Line cards:{v}     Interfaces on PSE2:{entry}   Interface PortID:{port_id}')
                               port_id = int(port_id)
                               print(port_id)
 
                               if port_id >= 19:
                                   #print(f'interface:{entry}  portID={port_id}   CPU_POS={port_cpu_pos}    REPLICATION=YES')
                                   if_info = [entry,'PSE2=YES',port_id,port_cpu_pos,'REPLICATION=YES']
                                   var_dict['IF_PSE2'].append(if_info)
                                   #===> *** This is the point that if i attempt to print var_dict, I get the Error during olist(): dictionary changed size during iteration
                               else:
                                   #print(f'interface:{entry},portID={port_id}   CPU_POS={port_cpu_pos}     REPLICATION=NO')
                                   if_info = [entry,'PSE2=YES',port_id,port_cpu_pos,'REPLICATION=NO']
                                   var_dict['IF_PSE2'].append(if_info)
                           else:
                                #it means the interface is on single PSE. No replication is applicable. Just check threshold between incoming and outgoing rate.
                                if_info = [entry,'PSE2=NO',int(port_id),port_cpu_pos,'REPLICATION=NO']
 
                                var_dict['IF_PSE1'].append(if_info)
    #3) Retrieve Incoming and Outgoing rate
    #==>To be deleted: This is a temporary hardcoded value for testing.
    olist_data[2] = """RP/0/RP0/CPU0:R7-P1#show mfib route rate 230.207.200.1
    IP Multicast Forwarding Rates
    (Source Address, Group Address)
    Incoming rate: pps/bps (Incoming node)
    Outgoing rate:
    Node: (Outgoing node) : pps/bps
    (50.50.50.2,230.207.200.1)
    Incoming rate : 1013 / 8127181 (0/5/CPU0)
     Outgoing rate :
     Node : 0/5/CPU0 : 1974 / 15828597. >> it shows double as O-list is on 2 PSE’s.
     Node : 0/9/CPU0 : 993 / 7966755     
    Incoming rate : 9999 / 8127181 (0/5/CPU0)
     Outgoing rate :
     Node : 0/5/CPU0 : 198 / 15828597. >> it shows double as O-list is on 2 PSE’s.
     Node : 0/9/CPU0 : 992 / 7966755      """
 
    #Format olist_data[2]
    under_Outgoing = False
    list_node = olist_data[2].split('\n')
    for entry in list_node:
             
            in_rate = re.findall(r'Incoming\srate\s:\s(\d+)\s\/\s\d+', entry)
            if in_rate:
                   
                  #Incoming Rate information found. Save it to Node dictionary:
                  save_rate = in_rate
            outgoing = re.findall(r'(Outgoing rate:)', entry)
            if outgoing:
                 #That means it is under the "Outgoing rate:" section.
                 under_Outgoing = True
            else:
                 under_Outgoing = False
 
                
            if entry.strip().startswith('Node'):
 
                 cpu_node_pos = re.findall(r'(\d\/\d)',entry)
                 if cpu_node_pos:
                      #cpu_node_pos = cpu_node_pos.strip()
                      pass
 
                 node = re.findall(r'Node\s:\s.*?\s:\s(\d+)\s/\s\d+',entry)
                 if node:
 
                      #Now save data: incoming rate, outgoing rate, CPU_pos_info, mcast_group
                      node_data =  [save_rate, node, cpu_node_pos]
                      var_dict['NODE'].append(node_data)
                      #print(f'Incoming Rate:{save_rate}    Outgoing Rate:{node}   CPU_INFO:{cpu_node_pos}')
 
     
     
    return var_dict
     
 
def ssh_nodes(myuser, nodepass,  host,mcastgroup):
 
    print(f'* Connecting to node for username:{USERNAME}')
 
    remote_conn_pre = paramiko.SSHClient()
    remote_conn_pre
    remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    host = host.strip()
    remote_conn_pre.connect(host, username=myuser,password=nodepass,look_for_keys=False,allow_agent=False)
 
    print(f'* SSH connection established to {host}')
    remote_conn = remote_conn_pre.invoke_shell()
    remote_conn.send('terminal length 0\n')
    remote_conn.send('show mrib route %s \n' %(mcastgroup))
    time.sleep(15)
    remote_conn.send('show mfib route rate %s \n' %(mcastgroup))
    time.sleep(15)
    remote_conn.send('show platform \n')
    time.sleep(15)
    output=remote_conn.recv(65535)
    time.sleep(10)
    remote_conn.close()
    output_str = output.decode('utf-8')
    return output_str
 
def get_credentials():
    #Assuming USERNAME is already entered
    inputpass = getpass.getpass()
    inputpass = inputpass.strip('\n')  
    return inputpass
 
def verify_threshold(node_PS_if_list):
    print(f'******************* NOW LISTING ***********************')
    print(node_PS_if_list)
 
def main():
 
    try:
        #Get secure password from user. Username is a global variable USERNAME
        node_pass = get_credentials()
    except Exception as err:
        print(f'Error during get_credentials() call: {err}')
     
    try:
        get_platform_data = ssh_nodes(USERNAME, node_pass, TARGET_SERVER, MGROUP)
    except Exception as err:
        print (f'Error during get_platform_data:{err}')
     
    try:
        get_analysis_int = olist(get_platform_data)
    
    except Exception as err:
       print(f'Error during olist(): {err}')
 
    try:
        verify_threshold(get_analysis_int)
    except Exception as err:
        print(f'Error during verify_threshold(): {err}')
    
    sys.exit(0)
 
if __name__ == '__main__':
    main()
 
  
#===end====================
Reply
#2
This is a defaultdict, and a defaultdict is a dict like object, see: https://docs.python.org/3/library/collec...efaultdict
so the output doesn't look like what you might expect, yet it's perfectly good data:
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import collections
>>> zz =  {'PSE2': ['0/7/CPU0', '1/0/CPU0', '1/2/CPU0'], 'IF_PSE1': [['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'IF_PSE2': [['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'NODE': [[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]}
>>>
>>> sorted(zz.items())
[('IF_PSE1', [['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']]), ('IF_PSE2', [['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']]), ('NODE', [[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]), ('PSE2', ['0/7/CPU0', '1/0/CPU0', '1/2/CPU0'])]
>>>
>>> zz['NODE'][0][1]
['1974']
>>> zz['PSE2']
['0/7/CPU0', '1/0/CPU0', '1/2/CPU0']
>>>
>>> zz.keys()
dict_keys(['PSE2', 'IF_PSE1', 'IF_PSE2', 'NODE'])
Reply
#3
So if I want to list values 1, 2, 3, 4, 5, I did:
'NODE': [[['1013'], ['1'], ['5/6']], [['1013'], ['2'], ['0/6']], [['1013'], ['3'], ['0/9']], [['1013'], ['4'], ['0/1']], [['1013'], ['5'], ['5/6']], [['1013'], ['6'], ['0/6']], [['1013'], ['7'], ['0/9']], [['1013'], ['8'], ['0/1']]]})
expect 1 at position = ['1']
expect 2 at position = ['2']
node position 3 = ['3']
node position = ['4']
node position = ['5']


Question:
placing a counter "i" in the for loop like in the below would do it.
It is not clear to me where would be the 'range' command placed to limit the list until it reaches the end?

Thank you!

i@ubuntu:~/Downloads/scripts$

1
2
3
4
5
6
7
8
9
10
11
12
def verify_threshold(node_PS_if_list):
    print(f'******************* NOW LISTING ***********************')
    print(node_PS_if_list)
    for k, v in node_PS_if_list.items():
        if k ==  "NODE":
 
 
            print (f'expect 1 at position 1 =  {v[i][1]}')
            print (f'expect 2 at  position 1 = {v[i][1]}')
            print (f'node position 3 =         {v[i][1]}')
            print (f'node position           = {v[i][1]}')
            print (f'node position           = {v[i][1]}')
Reply
#4
well, if you look at the code that I below, there are 4 keys
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> import collections
>>> zz = {'PSE2': ['0/7/CPU0', '1/0/CPU0', '1/2/CPU0'], 'IF_PSE1': [['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'IF_PSE2': [['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'NODE': [[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]}
>>>
>>> zz.keys()
dict_keys(['PSE2', 'IF_PSE1', 'IF_PSE2', 'NODE'])
>>>
>>> zz['PSE2']
['0/7/CPU0', '1/0/CPU0', '1/2/CPU0']
>>>
zz['IF_PSE1']
[['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']]
>>>
>>> zz['IF_PSE2']
[['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']]
>>>
zz['NODE']
[[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]
There are only 4 item as seen with zz.keys()
then for example to breakdown the 'NODE' key:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
>>> for item in zz['NODE']:
...     print(item)
...
[['1013'], ['1974'], ['0/5']]
[['1013'], ['993'], ['0/9']]
[['9999'], ['198'], ['0/5']]
[['9999'], ['992'], ['0/9']]
>>>
>>> for item in zz['NODE']:
...     for item1 in item:
...         print(item1)
...
['1013']
['1974']
['0/5']
['1013']
['993']
['0/9']
['9999']
['198']
['0/5']
['9999']
['992']
['0/9']
>>>
So from this you should be able to drill down to what you want.
Reply
#5
Sorry if I still didn't get it.
Let's say if I need to list the items I highlighted below (they are always the zz[variable][1].
If possible, can you kindly tell me your way to get a for loop and iterate thru the 'variable' to increment it and make me always get value from position zz[variable][1]? Thanks in advance.


Let's say I need to list
(Apr-09-2019, 11:33 PM)Larz60+ Wrote: well, if you look at the code that I below, there are 4 keys
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> import collections
>>> zz = {'PSE2': ['0/7/CPU0', '1/0/CPU0', '1/2/CPU0'], 'IF_PSE1': [['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'IF_PSE2': [['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']], 'NODE': [[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]}
>>>
>>> zz.keys()
dict_keys(['PSE2', 'IF_PSE1', 'IF_PSE2', 'NODE'])
>>>
>>> zz['PSE2']
['0/7/CPU0', '1/0/CPU0', '1/2/CPU0']
>>>
zz['IF_PSE1']
[['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']]
>>>
>>> zz['IF_PSE2']
[['TenGigE0/7/0/3.1', 'PSE2=YES', 3, 'TenGigE0/7', 'REPLICATION=NO']]
>>>
zz['NODE']
[[['1013'], ['1974'], ['0/5']], [['1013'], ['993'], ['0/9']], [['9999'], ['198'], ['0/5']], [['9999'], ['992'], ['0/9']]]
There are only 4 item as seen with zz.keys()
then for example to breakdown the 'NODE' key:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
>>> for item in zz['NODE']:
...     print(item)
...
[['1013'], ['1974'], ['0/5']]
[['1013'], ['993'], ['0/9']]
[['9999'], ['198'], ['0/5']]
[['9999'], ['992'], ['0/9']]
>>>
>>> for item in zz['NODE']:
...     for item1 in item:
...         print(item1)
...
['1013']
[b]['1974'][/b]
['0/5']
['1013']
[b]['993'][/b]
['0/9']
['9999']
[b]['198'][/b]
['0/5']
['9999']
[b]['992'][/b]
['0/9']
>>>
So from this you should be able to drill down to what you want.
Reply
#6
Ok:
1
2
zz['IF_PSE1']
[['TenGigE0/5/0/21.201', 'PSE2=NO', 21, 'TenGigE0/5', 'REPLICATION=NO'], ['TenGigE0/7/0/3.1', 'PSE2=NO', 3, 'TenGigE0/7', 'REPLICATION=NO']]
It looks like you want the third element of each list, so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> for key, outerlist in zz.items():
...     for innerlist in outerlist:
...         print(key, innerlist[2])
...
PSE2 7
PSE2 0
PSE2 2
IF_PSE1 21
IF_PSE1 3
IF_PSE2 3
NODE ['0/5']
NODE ['0/9']
NODE ['0/5']
NODE [['9999'], ['992'], [...]]
>>>
Is this correct?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Strange behavior list of list mmhmjanssen 3 1,610 May-09-2024, 11:32 AM
Last Post: mmhmjanssen
  Can i clean this code ? BSDevo 8 2,292 Oct-28-2023, 05:50 PM
Last Post: BSDevo
  No matter what I do I get back "List indices must be integers or slices, not list" Radical 4 2,601 Sep-24-2023, 05:03 AM
Last Post: deanhystad
  How do I call sys.argv list inside a function, from the CLI? billykid999 3 1,892 May-02-2023, 08:40 AM
Last Post: Gribouillis
  Delete strings from a list to create a new only number list Dvdscot 8 3,346 May-01-2023, 09:06 PM
Last Post: deanhystad
  List all possibilities of a nested-list by flattened lists sparkt 1 1,769 Feb-23-2023, 02:21 PM
Last Post: sparkt
  Сheck if an element from a list is in another list that contains a namedtuple elnk 8 3,402 Oct-26-2022, 04:03 PM
Last Post: deanhystad
Question Keyword to build list from list of objects? pfdjhfuys 3 2,615 Aug-06-2022, 11:39 PM
Last Post: Pedroski55
  Clean Up Script rotw121 2 1,816 May-25-2022, 03:24 PM
Last Post: rotw121
  Split a number to list and list sum must be number sunny9495 5 3,827 Apr-28-2022, 09:32 AM
Last Post: Dexty

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020