Perspective Memory String Array Write

I am getting to know the tags more and have been having trouble getting information to write to a memory string array. I have a multiple selection drop down that I am taking the values and trying to write to a tag. The problem is it will not write or if I use a loop write over the old value and not append (I can't find where if there is a system perspective function to do this)

Without a loop I have this:

def runAction(self, event):
	supervisors = self.getSibling("superDropDown").getChild("supervisorSelect").props.value
	system.tag.writeBlocking('[default]Alarm/supervisors', [self.session.custom.JW.alert.supervisors])
	

And then when I add a loop and it actually writes but write over this is what I have so far:

def runAction(self, event):
	supervisors = self.getSibling("superDropDown").getChild("supervisorSelect").props.value

	for i in supervisors:
		system.tag.writeBlocking("[default]Alarm/supervisors", i )

Tags are meant to be written as a whole. Read the tag to get the current array. Construct a new array modified as desired, then write that back to the tag.

the length of the array changes so I don't know if that is the problem? But I get this error
ValueError: Length of values does not match length of paths.

So I tried that before and it didn't work. This was my thought process of how I would go about that:

def runAction(self, event):
	addition = self.getSibling("superDropDown").getChild("supervisorSelect").props.value
	
	
	supervisors = system.tag.readBlocking ("[default]Alarm/supervisors")
	values = supervisors.append (addition)
	system.tag.writeBlocking('[default]Alarm/supervisors', values)

If you could tell me where I am going wrong that would be great!

You need to supply lists to writeBlocking. If writing a single tag, and its value is a list, it still must be encapsulated in another list.

{ readBlocking has a backward compatibility quirk that lets it handle a single tag path. But still returns a list (of one) of qualified values.}

Your script is not supplying lists to the functions, and not properly extracting your actual tag value from the read list of qualified values. Please review the documentation for these functions again.

I am so sorry but still very confused. I tried looking through the manual but did not find anything. Would you be able to provide an example of the syntax you are trying to outline.

Are you saying it should be something as follows:


# Create a list with the tag paths to be updated.
paths = ["[default]Folder/Tag_A","[default]Folder/Tag_A"]
 
# Create a list with the update values, one value for each path.
values = [1,2]
 
# Execute the write operation.
system.tag.writeBlocking(paths, values)

which would have Tag_A have both 1 and 2?

There are examples and explanations of the parameters and return values for each of these functions:

system.tag.readBlocking()

system.tag.writeBlocking()

No, Tag_A would get just that last value.

Wrong:
system.tag.writeBlocking('[default]Alarm/supervisors', values)
Right
system.tag.writeBlocking(['[default]Alarm/supervisors'], [values])

system.tag.writeBlocking(['[default]Alarm/supervisors'], [values])

{ The OP is trying to write to an array tag. }

Fixed, thanks, Phil. I assumed that values was already an array mucha like "args" in the documentation examples. It would have tripped me up too.

1 Like

Unfortunately that still did not work.

def runAction(self, event):
	supervisors = self.getSibling("superDropDown").getChild("supervisorSelect").props.value
	
	system.tag.writeBlocking(['[default]Alarm/supervisors'], [supervisors])
	system.perspective.print(supervisors)

I printed the supervisors to make sure it was pulling the data and it was able to print this array in the console:
14:13:06.604 [Browser Thread: 61073] INFO Perspective.Designer.Workspace - : [u' 5542', u' 925']

Hmm. If that tag is a string array, I would have expected that to work.

Hmmm.... Well that makes me feel a little better that I am not going crazy and making a obvious mistake on why this isn't working

Thank you!

I think I figured it out that since it is from a database it is adding a u before the string not allowing the write for the tag

The u in [u' 5542'] just means that the string is unicode encoded. It is not actually part of the string.

Throw this into a script console to see what I mean.

test = [u' 5542']
print test[0]
1 Like
def runAction(self, event):
	supervisors = self.getSibling("superDropDown").getChild("supervisorSelect").props.value
	data_email =system.db.runNamedQuery("Select_JER_Supervisor_Email")
	supers_email = system.dataset.toPyDataSet (data_email)
	select_email = []
	for num in supers_email:
		for select_num in supervisors:
			if num[0] == select_num:
				select_email.append(str(num[1]))
	system.tag.writeBlocking(["[default]Alarm/supervisor_email"], [select_email])

this is what I came up with that worked and just ended up needing to convert the index to string in order to read it without seeing the u for unicde and write to a variable and then write that variable array to the array tag

This can be simplified a bit.

first, this:

for select_num in supervisors:
	if num[0] == select_num:

is equivalent to

if num[0] in supervisors:

then, we can put the whole loop in a list comprehension:

select_email = [num[1] for num in supers_email if num[0] in supervisors]

I'd also suggest finding a more meaningful name than 'num' for your variable.

edit:
May I ask what that whole thing is about ?

1 Like

I don't know what this means or why it's important. Assuming that num[1] is a string, unicode or not, the str() is doing nothing but taking up execution time, however small that may be.

I would also suggest using the column names instead of their index, so that whomever comes after you will have a little easier time figuring out what's going on.

1 Like

I agree.
You can use column names instead of index when accessing things in a pyDataSet.
It makes the whole thing that much clearer.

They can also be unpacked, but that might be unpractical if there are more columns than you need to use. But let's say your supers_mail dataset has 2 columns user_name and user_email, you can do this:

for name, email in supers_mail:
    print name, email

for row in supers_mail:
    print row['user_name'], row['user_email']

for row in supers_mail:
    print row[0], row[1]

Those are equivalent when using pyDataSets.
With the little exception that the first one, unpacking, requires you to use as many variables as there are elements to unpack, so it won't work if your dataset has more than 2 columns.
If it had a third column user_phonenum, you'd need to do this, even if you don't need the phone number:

for name, email, num in supers_mail:
    print name, email
1 Like