cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1806
Views
30
Helpful
8
Replies

Unable to iterate over a nested list in Python ?

I am creating a service module apply interface configs. I am facing a number of errors in my Python code while referencing a leaf in a nested list.

 

---YANG---:

 

 

list endpoints {
key device;
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
}
list intf {
key intf_id;
leaf intf_id {
type string;
}

}

}

---Python---:

template = ncs.template.Template(service)
vars = ncs.template.Variables()

for i in service.intf[intf_id]:
vars.add('intf-id', i.intf_id)
#vars.add('port-id', i.port_id)
template.apply('device_provisioning-template', vars)

 

---error I am getting---:

 

errors: reason: Python cb_create error. 'ListElement' object has no attribute 'intf'

1 Accepted Solution

Accepted Solutions

snovello
Cisco Employee
Cisco Employee

hello Bashar,

you have nested lists , intf inside endpoints so you will need nested for loops

 

for endpoint in service.endpoints:

   for interface in endpoint.intf:

     vars.add('intf-id', interface.intf_id )

 

the error is saying there is no intf attribute in service, that is because the intf list is nested inside the endpoints list.

 

Stefano

View solution in original post

8 Replies 8

tcragg1
Cisco Employee
Cisco Employee

I think the problem is that you are trying to iterate over a list element rather than over the list as a whole. Try removing the "[intf_id]" from the end of the for loop line to make it iterate over the list.

snovello
Cisco Employee
Cisco Employee

hello Bashar,

you have nested lists , intf inside endpoints so you will need nested for loops

 

for endpoint in service.endpoints:

   for interface in endpoint.intf:

     vars.add('intf-id', interface.intf_id )

 

the error is saying there is no intf attribute in service, that is because the intf list is nested inside the endpoints list.

 

Stefano

Nested for loops in Python were needed. Awesome now it works like a charm. 

 

Thank you Stefano.

Hi snovello,

 

In the above example code, I am not clear about the usage of passing the object "service" passed in statement

"template = ncs.template.Template(service)".

when we pass "service" as object what difference it makes as compared to if we pass the object "endpoint" as

"template = ncs.template.Template(endpoint)" which is essentially "service.endpoints" .Thanks.

 

 

for endpoint in service.endpoints:

for interface in endpoint.intf:

vars.add('intf-id', interface.intf_id )

template = ncs.template.Template(endpoint)

 

vs

 

for endpoint in service.endpoints:

for interface in endpoint.intf:

vars.add('intf-id', interface.intf_id )

template = ncs.template.Template(service)

It forms the initial context for any xpath expressions in the template.

ZAhmad04890
Level 1
Level 1

Hi, when using nested for loops or similar logic , how can we print the values of service variables e.g "endpoint.intf"

or "service.endpoint" ? as shown below, in iPython editor? I believe we also need to import some ncs service libraries for this functionality to work and need a running NSO service instance as well? Thanks

 

for endpoint in service.endpoints:

  for interface in endpoint.intf:

      print(interface, endpoint)

         

vars.add('intf-id', interface.intf_id )

So, you can use ncs_pycli (https://github.com/NSO-developer/ncs_pycli) to do it from the command line, that allows you to easily investigate the data tree. Of course you can just run the same things directly in any tool you want.

Hello,

there are a couple of nice githubs that do this very confortably for you. one starts  ipython straight from the nso cli, the other is a shell wrapper.

see https://www.google.com/search?q=cisco+nso+ipython

I use a tiny script, which I include here, you can copy and paste into a file that is in your path, I have it called ncs_py_cli

#!/usr/bin/env python3
from __future__ import print_function
import ncs
import IPython

if __name__ == '__main__':
    m = ncs.maapi.Maapi()
    sess = m.start_user_session('admin', 'system', [])
    trans = m.start_trans(ncs.RUNNING, ncs.READ_WRITE)

    x = ncs.maagic.get_root(trans)

    print("Your maagic object 'x -> %s' is now prepared... go have some fun!" %
          (str(x)))
    IPython.embed(display_banner=False)

it starts an ipython session where you have the variables m, sess, trans, and x and from there you can navigate to where you want.