i made a python toolbox with various tools to interact with a Portal. i set it up using a global variable that would hold the portal info so i dont have to get it for every tool. This created issues as other tools not in this toolbox would raise errors that this global varibale is not defined.
i defined the variable the Toolbox class __init__, i am confused how the __init__ method of the Toolbox class is being called when that toolbox is not open
That aside i know its not great practice to use global variables and i cant control the above issues so i went down the road of trying to pass the now non-global variable between the tools in the Toolbox by setting it as an attribute of Toolbox in the __init__ method and then inheriting the Toolbox class in each Tool Class
This ran in to the problem
"TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, Toolbox"
so i can use the inheritance method as both of these classes must be already inherited into some class when it runs.
How can i pass variables either from the Toolbox class to each tool or even just between tools?
Solved! Go to Solution.
I've attached a simple example (counts the number of times UpdateParameters is called) of how I share data between tools in a python toolbox. My guess is that it is similar to what you are already doing - using globals. There probably is a more elegant way but I've run into the same problems that you describe and finally settled on this because it does work.
# -*- coding: utf-8 -*-
import arcpy
tool_1_data = dict()
tool_2_data = dict()
class Toolbox(object):
def __init__(self):
self.label = "Toolbox"
self.alias = "toolbox"
self.tools = [Tool_1, Tool_2]
def get_tool_data (tool_data_dict, tool_data_key):
if tool_data_key in tool_data_dict.keys():
return tool_data_dict[tool_data_key]
else:
return None
class Tool_1(object):
def __init__(self):
self.label = "Tool_1"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
global tool_1_data
if len(tool_1_data) == 0:
tool_1_data = {'my_count': 0}
my_count = arcpy.Parameter(displayName="My Count", name="my_count", datatype="GPLong", parameterType="Optional", direction="Input")
other_count = arcpy.Parameter(displayName="Other Count", name="other_count", datatype="GPLong", parameterType="Optional", direction="Input")
return [my_count, other_count]
def updateParameters(self, parameters):
global tool_1_data
global tool_2_data
tool_1_data['my_count'] += 1
parameters[0].value = get_tool_data(tool_1_data, 'my_count')
parameters[1].value = get_tool_data(tool_2_data, 'my_count')
return
def execute(self, parameters, messages):
return
class Tool_2(object):
def __init__(self):
self.label = "Tool_2"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
global tool_2_data
if len(tool_2_data) == 0:
tool_2_data = {'my_count': 0}
my_count = arcpy.Parameter(displayName="My Count", name="my_count", datatype="GPLong", parameterType="Optional", direction="Input")
other_count = arcpy.Parameter(displayName="Other Count", name="other_count", datatype="GPLong", parameterType="Optional", direction="Input")
return [my_count, other_count]
def updateParameters(self, parameters):
global tool_1_data
global tool_2_data
tool_2_data['my_count'] += 1
parameters[0].value = get_tool_data(tool_2_data, 'my_count')
parameters[1].value = get_tool_data(tool_1_data, 'my_count')
return
def execute(self, parameters, messages):
return
i could not figure out a way to do this, not sure that it is possible.
instead i went back to the global but I am creating the variable in the init of each tool if it hasn't been created. i have concluded that the changes to the Toolbox class i made must be getting inherited into Toolbox class that all tools use.
if anyone knows how to pass the variables btw tools let me know as i would prefer to not use the global
I've attached a simple example (counts the number of times UpdateParameters is called) of how I share data between tools in a python toolbox. My guess is that it is similar to what you are already doing - using globals. There probably is a more elegant way but I've run into the same problems that you describe and finally settled on this because it does work.
# -*- coding: utf-8 -*-
import arcpy
tool_1_data = dict()
tool_2_data = dict()
class Toolbox(object):
def __init__(self):
self.label = "Toolbox"
self.alias = "toolbox"
self.tools = [Tool_1, Tool_2]
def get_tool_data (tool_data_dict, tool_data_key):
if tool_data_key in tool_data_dict.keys():
return tool_data_dict[tool_data_key]
else:
return None
class Tool_1(object):
def __init__(self):
self.label = "Tool_1"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
global tool_1_data
if len(tool_1_data) == 0:
tool_1_data = {'my_count': 0}
my_count = arcpy.Parameter(displayName="My Count", name="my_count", datatype="GPLong", parameterType="Optional", direction="Input")
other_count = arcpy.Parameter(displayName="Other Count", name="other_count", datatype="GPLong", parameterType="Optional", direction="Input")
return [my_count, other_count]
def updateParameters(self, parameters):
global tool_1_data
global tool_2_data
tool_1_data['my_count'] += 1
parameters[0].value = get_tool_data(tool_1_data, 'my_count')
parameters[1].value = get_tool_data(tool_2_data, 'my_count')
return
def execute(self, parameters, messages):
return
class Tool_2(object):
def __init__(self):
self.label = "Tool_2"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
global tool_2_data
if len(tool_2_data) == 0:
tool_2_data = {'my_count': 0}
my_count = arcpy.Parameter(displayName="My Count", name="my_count", datatype="GPLong", parameterType="Optional", direction="Input")
other_count = arcpy.Parameter(displayName="Other Count", name="other_count", datatype="GPLong", parameterType="Optional", direction="Input")
return [my_count, other_count]
def updateParameters(self, parameters):
global tool_1_data
global tool_2_data
tool_2_data['my_count'] += 1
parameters[0].value = get_tool_data(tool_2_data, 'my_count')
parameters[1].value = get_tool_data(tool_1_data, 'my_count')
return
def execute(self, parameters, messages):
return
Thansk for replying, that is basically what i have done, i just have the global defined in a function outside of the Tool class and called within the __inti__ of the tool so it only needs to be made once.