Global value can't be assigned inside the expression in python toolbox

267
7
01-17-2020 04:26 AM
Highlighted
New Contributor

I am trying to call the global value 'total_rows' inside the expression. But I am getting an error.

and my code is

def execute(self, parameters, messages):
"""The source code of the tool."""
   inputdataset = parameters[0].valueAsText #getting the parameters

   count_rows = arcpy.GetCount_management(inputdataset)
   total_rows = int(count_rows.getOutput(0))

expression = '''

   def getCitation(p_dataset_id):
      global total_rows
      if(total_rows == 5):
            ds=PanDataSet(p_dataset_id)
   return ds.citation

'''

Reply
0 Kudos
7 Replies
Highlighted
MVP Regular Contributor

Using globals in a Python toolbox or script tool is a bit tricky.  The toolbox/script creates a number of instances during function calls.  It is best to declare a global in getParameterInfo as this function appears to be called only once.  An example of a toolbox script that uses "junk" as a global variable is:

import arcpy

class Toolbox(object):
def __init__(self):
self.label = "Toolbox"
self.alias = ""
self.tools = [Tool]


class Tool(object):
def __init__(self):
self.label = "Tool"
self.description = ""
self.canRunInBackground = False

def getParameterInfo(self):
global junk
junk = None
param0 = arcpy.Parameter(
displayName="Something",
name="something",
datatype="GPString",
parameterType="Required",
direction="Input"
)
params = [param0]
return params

def isLicensed(self):
return True

def updateParameters(self, parameters):
global junk
junk = "XYZ"
return

def updateMessages(self, parameters):
return

def execute(self, parameters, messages):
global junk
arcpy.AddMessage("The value junk is: " + junk)
return

For more discussion see the following:

Using Global Variables in Python Toolbox?

Python toolbox tool objects do not remember instance variables between function calls?

Highlighted
New Contributor

Inside the expression the global value is not working. I want to get the number of row values inside the expression.

Reply
0 Kudos
Highlighted
MVP Esteemed Contributor
expression = '''
global total_rows
total_rows=5
def getCitation(p_dataset_id):
if(total_rows == 5):
ds=PanDataSet(p_dataset_id)
return ds.citation‍‍‍‍‍‍‍‍‍‍‍‍

so this didn't work either?

But I am not sure what it is the script is doing since there is nowhere in the script that collects information to compare to total rows

Reply
0 Kudos
Highlighted
New Contributor

No It didn't work as well. I am getting the same error. If it is outside the expression it works.

Right now I am just testing the code whether the global values can be assigned inside the expression.

I am sending the dataset id value to the server to collect the data. Within 30 seconds the server can handle 60 data if it is more than that it stops working.

So I want to get the total number of rows and if it's more than 60 rows I want to delay the processing.

Reply
0 Kudos
Highlighted
MVP Esteemed Contributor

you need to assign an initial value to the global somewhere, like outside the def in your enclosing expression

Highlighted
MVP Regular Contributor

Did you try something like indicating that total_rows was a global in the "execute" function (line 3) below:

def execute(self, parameters, messages):
"""The source code of the tool."""
global total_rows # indicate that total_rows is a global
inputdataset = parameters[0].valueAsText #getting the parameters

count_rows = arcpy.GetCount_management(inputdataset)
total_rows = int(count_rows.getOutput(0))

expression = '''

def getCitation(p_dataset_id):
global total_rows
if(total_rows == 5):
ds=PanDataSet(p_dataset_id)
return ds.citation

'''

I'm also puzzled by the indentation in the code snippet you posted.  Is the "expression" section (lines 9 -17) part of the "execute" function?  It may not be indented properly.

Reply
0 Kudos
Highlighted
MVP Regular Contributor

It's a string expression and is evaluated outside the scope of your current code so has no knowledge about any of your variables.

You need to insert the actual value into the string:

class YourTool(object):
def __init__(self):
etc...

def getParameterInfo(self):
etc...

def execute(self, parameters, messages):
"""The source code of the tool."""

inputdataset = parameters[0].valueAsText # getting the parameters

count_rows = arcpy.GetCount_management(inputdataset)
total_rows = int(count_rows.getOutput(0))

expression = '''
def getCitation(p_dataset_id):
total_rows = {}
if(total_rows == 5):
ds=PanDataSet(p_dataset_id)
return ds.citation
'''
.format(total_rows)
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Note - you can't indent the expression, or it won't be valid python syntax when the tool evaluates it - IndentationError: unexpected indent.  If you want your code to look cleaner and have the expression indented, you can use inspect.cleandoc(expression) 

inspect — Python 2.7 documentation 

inspect — Python 3.8 documentation 

inspect.cleandoc(doc)

Clean up indentation from docstrings that are indented to line up with blocks of code.

All leading whitespace is removed from the first line. Any leading whitespace that can be uniformly removed from the second line onwards is removed. Empty lines at the beginning and end are subsequently removed. Also, all tabs are expanded to spaces.

import inspect

class YourTool(object):
def __init__(self):
etc...

def getParameterInfo(self):
etc...

def execute(self, parameters, messages):
"""The source code of the tool."""

inputdataset = parameters[0].valueAsText # getting the parameters

count_rows = arcpy.GetCount_management(inputdataset)
total_rows = int(count_rows.getOutput(0))

expression = inspect.cleandoc('''
def getCitation(p_dataset_id):
total_rows = {}
if(total_rows == 5):
ds=PanDataSet(p_dataset_id)
return ds.citation
'''
.format(total_rows))‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Reply
0 Kudos