Hi guys,
Did anyone notice that system functions aren’t working in locally defined functions in Tag Change scripts? It works in any other context I tried (Gateway message handlers, Perspective scripts, Vision scripts, project scripts).
I wonder why.
Example:
Gateway Tag Change Script:
Change Trigger: Value
Path: [default]Global/test
Script:
def x():
system.util.getProjectName()
x()
Erorr in logs: NameError: global name 'system' is not defined
Inside your local function then you would have to do an import system.util. I can’t give you the technicals why but in a lot of areas of Ignition if you use a local function you end up needing to do that.
Personally I think the best practice, for a multitude of reasons, is to put the entire function logic inside a project script, and then call that function from the tag change script.
I think this get’s rid of the problem you are seeing, and it will make version control easier to do/possible.
I agree with you, I usually try to put everything in project scripts, but I’ve been dealing with a tiny bit of logic that’s very specify to its context. Thanks again.
Just import system is enough in any of these cases. It is a backwards-compatibility choice IA made some time ago that has gateway project event scripts use a legacy global variable rule. IMNSHO, it should have been ditched for v8.0. Hopefully it’s in the plan for v8.2.
The best work-around is to not write code in event scripts. Write functions in project script modules that accept the event (and any other local variables) as function arguments. So the event script can be a one-line function call. The functions in project script modules will not have the legacy scope issue.
So in a tag change script I cannot do this, correct? The error log indicates that this is not acceptable in a tag change script. Works in the script console but not in a UDT instance.
writePaths, writeVals = [], []
def computePoints(vals, pathFormat):
"""
Gets the availability, line count and target
appends values to writeValues
appends write path to write path with the specified format
"""
global writePaths
global writeVals
points = ["availableDuration", "lineCount", "targetCount"]
writePaths += [pathFormat.format(p) for p in points]
writeVals += [
sum([v["availableDuration"] for v in vals])/len(vals),
sum([v["lineCount"] for v in vals]),
sum([v["targetCount"] for v in vals])
]
Not only is that going to be weird in a gateway tag change event, but it begs for disaster if multiple different events call it at the same time (no thread safety). Wherever possible, write pure functions.