Calling tags to a Coordinate Container error

When I run this code:

	from itertools import product
				
	def get_iterator(op_strings):
		quads = ['Breakout_Operator_1_','Breakout_Operator_2_','Breakout_Operator_3_','Creeler_1_','Creeler_2_','Operator_1_','Operator_2_']
		return product(range(201,313), quads, op_strings)
			
	path = '[default]Heatset/Operator Assignments/{}/K Shift/{}Name'
	paths = [path.format(*p) for p in get_iterator(['Name'])]
	tag_qvals = system.tag.readBlocking(paths)
			
	cc_idx, tw_breaks = 0, [210,312]
	for i,p in enumerate(get_iterator(['Name'])):
		if 211 <= p[0] <= 300:
			continue
		cc_idx += int(p[0] > tw_breaks[cc_idx])
		cc_str = 'CoordinateContainer_{}'.format(cc_idx)
		tw_str = 'Tun{}'.format(p[0])
		pm_str = '{}Name'.format(p[1])
		self.parent.getChild(cc_str).getChild(tw_str).props.params[pm_str] = tag_qvals[i].value
		

I am getting an error that says: AttributeError: 'NoneType' object has no attribute 'props'
Actually, I can see it trying to attempt this as the value in the 201 Operator changes, but then reverts back to normal when it faults.
So I am looking at the path that it should be writing the tag_qvals to and I am just not seeing the issue.
When I print('self.parent.getChild' + cc_str + '.getChild' + '(' + tw_str + ')' + '.props.params.' + pm_str)
It all looks right:

self.parent.getChildCoordinateContainer_0.getChild(Tun201).props.params.Breakout_Operator_1_Name
self.parent.getChildCoordinateContainer_0.getChild(Tun201).props.params.Breakout_Operator_2_Name
self.parent.getChildCoordinateContainer_0.getChild(Tun201).props.params.Breakout_Operator_3_Name
self.parent.getChildCoordinateContainer_0.getChild(Tun201).props.params.Creeler_1_Name
self.parent.getChildCoordinateContainer_0.getChild(Tun201).props.params.Creeler_2_Name
self.parent.getChildCoordinateContainer_0.getChild(Tun201).props.params.Operator_1_Name
self.parent.getChildCoordinateContainer_0.getChild(Tun201).props.params.Operator_2_Name

Any help would be greatly apricated.

This means that your pathing is probably incorrect.

Where is this script being called from? Does the parent of this object have a child object named 'CoordinateContainer_0'? Does that object then have a child object named 'Tun201'?

If you were to manually add the path to one of the expected items you are trying to build a path to, what does that path look like? Does it differ any from what your script is giving you?

A better way to achieve this would be to put all the tag values into a custom list property on the root container of the view, and then bind all the child objects that need the values to the appropriate element in that list.

This would remove the need to grab each child in a script to pass data to it, and would simply your script to just a batch read of tags. This method would also be more tolerant to objects switching containers or parents/children or the names of the objects changing.

1 Like

When I look at the path with the property explorer in the script menu, i see this:

self.parent.getChild("CoordinateContainer_0").getChild("Tun201").props.params.Breakout_Operator_1_Name

Unless I am overlooking something...

If you change your script to write a set value to that path you got with the property explorer, does the script succeed in setting the value?

It definitely feels like you are building your current script around the structure of your current 'main' view that you are building. This script will be very fragile and any time you add or change around the main view or children of containers, you will have to change your script to match.

Am I correct in assuming that the child items of the coordinate containers are some sort of embedded view? If that is the case, you should change those views to take/build a tag path instead of manually passing the tag values to them with a script. Bindings are much more performant than scripts.

Change the embedded views to take a number between 201 and 313 as an IdNumber param. Then, have custom properties on the root container of the embedded view for each of the quad names, with each of the custom properties having an indirect tag binding of [default]Heatset/Operator Assignments/{1}/K Shift/quadNameHere. Use the IdNumber parameter of the embedded view as the source of the value for the one part of the indirect binding.

After that, change any of the bindings in the embedded view that were originally getting their values from the multiple parameters you were passing to the view, and change them to look at the new properties on the embedded view's root containers.

This method then requires no scripting/script executions to get the needed values and you only have to provide a single parameter to the view to make it work. And it should be more performant than your script.

Edit: Changed the instructions for adjusting the embedded views after I realized you are passing several values to the same items

Syntatically the path shuld be valid, so that leaves, spelling and case. Paths are case sensitive, so "Tun201" is different from "tun201".

Might just make sure you haven't accidentally used a different casing somewhere on one of the coordinate containers or whatever component Tun* is.

1 Like