Select to view content in your preferred language

ESRI python toolbox how to pass variables between tools

926
3
Jump to solution
12-06-2023 05:04 PM
AntEsk
by
Emerging Contributor

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?

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
DonMorrison1
Frequent Contributor

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

  

View solution in original post

3 Replies
AntEsk
by
Emerging Contributor

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 

0 Kudos
DonMorrison1
Frequent Contributor

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

  

AntEsk
by
Emerging Contributor

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.

 

0 Kudos