3

Is there a way to reference parameters in an ArcGIS Pro Python Toolbox by name, instead of by numeric index / positional argument?

I built a data entry tool in a Python Toolbox that has over 100 parameters. If I need to add, remove, or reorder any of these, it becomes a massive undertaking to edit every entry in updateParameters(), updateMessages(), and execute().

Update: I've deleted my attempt, because it's bad, and only user2856's accepted answer should be on record.

2
  • 2
    A tool interface with over 100 parameters seems insane to me and unusable to all but yourself. An alternative option is to take just 1 parameter, a configuration file. This could be a structured text file, the obviously format would be XML and then its your code that extracts the various parameters.
    – Hornbydd
    Jan 13, 2022 at 14:19
  • It is a bit insane, I agree. It's a bootleg replacement for an Access data entry form since we migrated into a file geodatabase. The parameters are all just data entry string/numeric fields that get enabled/disabled and pre-populated based on the selected project, and then we can add/update data as needed. A config file, or even just a formatted Excel data entry form that could be scraped, would work for entering brand new data, but wouldn't allow us to view / edit existing data. And the database is pretty big, spread across many related tables, so manual entry in ArcMap isn't really feasible
    – Brennan
    Jan 13, 2022 at 20:54

1 Answer 1

4

Don't use a global. Just create a dictionary whenever you need to access parameters, e.g. in updateParameters, updateMessages, execute, etc:

parameters = {p.name: p for p in parameters}

e.g.

def updateParameters(self, parameters):
    parameters = {p.name: p for p in parameters}
    etc...

def updateMessages(self, parameters):
    parameters = {p.name: p for p in parameters}
    etc...

def execute(self, parameters, messages):
    parameters = {p.name: p for p in parameters}
    etc...

Another option is to create a namedtuple (could be a good ArcGIS Pro Idea) so you can access by index (backwards compatibility) as well as name.

from collections import namedtuple

etc...

    def execute(self, parameters, messages):  
        parameters = namedtuple('Parameters', (p.name for p in parameters))(*parameters)
        # do something with parameters[0] or parameters.some_name
        etc...

There's an ArcGIS Idea to change the parameters type from a list to a NamedTuple that you can support.

4
  • I like this approach, thank you! It is working, but could you please help me understand how? getParameterInfo() only runs once and creates a list of arcpy.parameter objects. updateParameters() is called multiple times, but each time it seems to be converting the variable 'parameters' from a list to a dictionary. Shouldn't it remain a dictionary after the first operation of "parameters = {p.name: p for p in parameters}" and fail on subsequent ones? I must be missing something about how this python toolbox class works...
    – Brennan
    Jan 14, 2022 at 15:17
  • 1
    It's because of variable scope, which is standard python and not specifically related to ArcGIS tools. When you set parameters = {p.name: p for p in parameters} in any of those Tool methods, you are only redefining the local parameters variable inside that method, not overwriting the parameters variable that ArcGIS passed in to that method. Instead you could do my_parameter_dict = {p.name: p for p in parameters} and then work with the my_parameter_dict instead of the parameters list. Yes it creates the dict every single time, but the performance cost of doing so is negligible.
    – user2856
    Jan 14, 2022 at 20:16
  • 1
    @Brennan And you avoid the chance of subtle bugs creeping in, like if you create a global parameters dict that you populate on the first run of the tool, the way your code is written, it may not get updated with new parameters if you run the tool multiple times.
    – user2856
    Jan 17, 2022 at 2:39
  • Thank you @user2856! That makes sense. In testing why I didn't need to wrap this back into a list named parameters, I realized I had a huge blind spot in my Python. Assigning these dictionary values is just assigning the object of each arcpy.parameters object (not copying them), so when we updated the dictionary values we are updating the original parameters themselves. (stackoverflow.com/questions/2612802/…)
    – Brennan
    Jan 18, 2022 at 12:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.