Trying to use Python .strip() when cleaning data from a perspective form. Script runs on a [Create] button on the form. Anyone know why the I can’t use this command?
Can you show us a code sample?
" MyText = self.getSibling(“ProductName_0”).props.text.strip()
ProductName = MyText[:32] #only the first 32 char and remove leading and trailing spaces"
Causes:
com.inductiveautomation.ignition.common.script.JythonExecException: NameError: global name ‘strip’ is not defined
I have also tried
- MyText[:32].strip()
- strip(MyText[:32])
I think you’ve either left out some import context or your error message is not from the script you think it is.
I would expect that to be an error maybe for this attempt:
strip(MyText[:32])
Sorry, I’m working on this webpage
The [create].onClick code reads
msg = ''
CrLf = chr(13) + chr(10)
MyText = self.getSibling("ProductName_0").props.text
if len(MyText.strip()) < 3:
msg = "Product/Recipe must have more than 3 characters" + CrLf
MyText = self.parent.parent.getChild("CoordinateContainer_0").getChild("Why").props.text
if len(MyText.strip()) < 1:
msg += "Must have a reason for the changes" + CrLf
MyText = self.getSibling("HeatRPM_0").props.text
if not MyFunc.isanum(MyText):
msg += "Heat Rotations Per Minute, must be a number" +CrLf
MyText = self.getSibling("CoolRPM_0").props.text
if not MyFunc.isanum(MyText):
msg += "Cooling Rotations Per Minute, must be a number" +CrLf
MyText = self.getSibling("HeatUpC_0").props.text
if not MyFunc.isanum(MyText):
msg += "Heat Up degrees Celsius, must be a number" +CrLf
MyText = self.getSibling("HeatOilC_0").props.text
if not MyFunc.isanum(MyText):
msg += "Heat Set Oil Temp Celsius, must be a number" +CrLf
MyText = self.getSibling("HeatBedC_0").props.text
if not MyFunc.isanum(MyText):
msg += "Heat Set Bed Temp Celsius, must be a number" +CrLf
MyText = self.getSibling("CoolC_0").props.text
if not MyFunc.isanum(MyText):
msg += "Cool/Packout Temp Celsius, must be a number" +CrLf
MyText = self.getSibling("HeatTime_0").props.text
delm = MyText.find(":")
if delm <0:
msg += "Heat Set time, must conform to Hours:Minutes" +CrLf
else:
hh = int(MyText[:delm])
mm = int(MyText[delm+1:])
if hh >24 or hh<0:
msg += "Heat Set time, must have 0-24 hours" +CrLf
if mm >59 or mm<0:
msg += "Heat Set time, must have 0-59 minutes" +CrLf
if msg <> '':
self.session.custom.PopUpResults = ''
self.session.custom.PopUpLabel = 'Message'
self.session.custom.PopUpText = msg
self.session.custom.PopUpBtns = 'OK'
system.perspective.openPopup('CreatePopUp','MsgBox')
else:
MyText = self.getSibling("ProductName_0").props.text.strip()
ProductName = MyText[:32] #only the first 32 char and remove leading and trailing spaces
MyText = self.parent.parent.getChild("CoordinateContainer_0").getChild("Why").props.text.strip()
Why = MyText[:64]
HeatRPM = float(self.getSibling("HeatRPM_0").props.text)
CoolRPM = float(self.getSibling("CoolRPM_0").props.text)
HeatUpC = float(self.getSibling("HeatUpC_0").props.text)
HeatOilC = float(self.getSibling("HeatOilC_0").props.text)
HeatBedC = float(self.getSibling("HeatBedC_0").props.text)
CoolC = float(self.getSibling("CoolC_0").props.text)
HeatTime = strip(self.getSibling("HeatTime_0").props.text)
params = {
"ProductName":ProductName,
"HeatRPM":HeatRPM,
"CoolRPM":CoolRPM,
"HeatUpC":HeatUpC,
"CoolRPM":CoolRPM,
"HeatOilC":HeatOilC,
"HeatBedC":HeatBedC,
"HeatTime":HeatTime,
"CoolC":CoolC,
"Who":self.session.props.auth.user.userName,
"Why":Why}
system.db.runUpdateQuery("AddRecipeRow",params)
self.parent.Vis(0)
When I click [create] and jump back to the gateway screen, the last message is always:
BtnCreate is the name of the button I’m clicking on.
That is all the context I can think of…
If you're going to use the strip
function like this you need to import it first:
from string import strip
Surround code you post in triple back-ticks and it will preserve the formatting.
```
code goes here
```
Thanks! and will do.
To expand a bit on Kevin’s statement:
strip()
is a builtin method on string instances - so as long as $reference.props.text
is a string, you can call .strip()
on it just fine.
But strip()
is not an automatic top level builtin - if you want to statically call string.strip
, you must import it, and then pass a string instance as the first argument.
It’s the same method (basically) but two different call patterns. The instance method is much more idiomatic in this case.
I Dig it. I was troubleshooting the wrong line of code. I thought I had exhausted all possibilities, but it was complaining about a different line of code than I was modifying. Is there a way I can determine which line the error is occurring in the log? - so I’m not barking up the wrong tree in the future.
If you ‘expand’ the error message (the plus icon) it should show a stacktrace with a distinct line number from Jython. We do some trickery with script compilation behind the scenes, but the line numbers in the errors should be accurate to your script.
com.inductiveautomation.ignition.common.script.JythonExecException: NameError: global name ‘strip’ is not defined
at org.python.core.Py.NameError(Py.java:261)
at org.python.core.PyFrame.getglobal(PyFrame.java:265)
at org.python.pycode.pyx330.runAction$1(:70)
at org.python.pycode.pyx330.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyFunction.function___call(PyFunction.java:474)
at org.python.core.PyFunction.call(PyFunction.java:469)
at org.python.core.PyFunction.call(PyFunction.java:464)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:843)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:825)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:689)
at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:994)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:754)
at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:133)
at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:71)
at com.inductiveautomation.perspective.gateway.action.ActionDecorator.runAction(ActionDecorator.java:18)
at com.inductiveautomation.perspective.gateway.action.SecuredAction.runAction(SecuredAction.java:44)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:263)
at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:252)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:221)
at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.python.core.PyException: NameError: global name ‘strip’ is not defined
… 28 common frames omitted
I could not decipher a line number out of here.
Hmm, interesting. I’m not sure why we’re not logging them to the gateway, but if I do the same in a script and then fire it in the designer, I do get a useful line number:
com.inductiveautomation.ignition.common.script.JythonExecException
Traceback (most recent call last):
File "<function:runAction>", line 2, in runAction
NameError: global name 'strip' is not defined
at org.python.core.Py.NameError(Py.java:261)
at org.python.core.PyFrame.getglobal(PyFrame.java:265)
at org.python.pycode._pyx8.runAction$1(<function:runAction>:2)
at org.python.pycode._pyx8.call_function(<function:runAction>)
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyFunction.function___call__(PyFunction.java:474)
at org.python.core.PyFunction.__call__(PyFunction.java:469)
at org.python.core.PyFunction.__call__(PyFunction.java:464)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:849)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:831)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:689)
at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:1000)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:754)
at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:133)
at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:71)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:263)
at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:252)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:221)
at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.python.core.PyException
Traceback (most recent call last):
File "<function:runAction>", line 2, in runAction
NameError: global name 'strip' is not defined
... 27 more
Ignition v(Dev Version)
Java: Azul Systems, Inc. 11.0.11
Definitely would be good to have that in the logged message.
In the future, I’ll try that before giving up and starting a thread.
Thanks,
I filed a ticket so we can see about getting better error messages to the gateway logs. It looks like it’s just being truncated by accident.