Select to view content in your preferred language

How to create python Tool that maintains input-derived state between runs

1215
5
Jump to solution
03-23-2024 12:43 PM
sbrowneotogo
Emerging Contributor

Hello ESRI community, I'm a python developer who's new to ArcGIS Pro and trying to get started on developing a tool. I read through a bunch of documentation and resources but still struggling to sketch out an architecture for what I'm trying to achieve and I'm hoping a veteran can point me in the right direction!

Here's the outline of what I'm trying to build, and I'm happy to provide more detail or context as required:

  • For 1 or more variables, take as user input a series of thresholds that define categories. For instance, it might look like this:
rules=[ 
    {'min_val':0, 'max_val':10, 'cat':'Low'}, 
    {'min_val':10, 'max_val':25, 'cat':'Medium'}, 
    {'min_val':25, 'max_val':100, 'cat':'High'} 
]

where the min_val and max_val determine a category (values between 0 and 10 are 'Low' etc)

  • This would be displayed to the user with default values that they can modify.
  • The user would select a variable from a list of options, modify the values, and then select a different variable and modify that one as well.
  • When they're done changing thresholds, I would run some processing using the thresholds.
  • Here's the tricky part: after running the tool, I want them to be able to pull up the tool again with the previously selected thresholds as the defaults.

    I see how to set default values in a python Toolbox, but I'm wondering how (and whether) it's possible to dynamically set defaults based on previous runs.

    Thanks to anyone who can provide pointers!

0 Kudos
1 Solution

Accepted Solutions
Dale_Honeycutt
Frequent Contributor

Ha! You've discovered the stateless nature of GP Tools.  It can be infuriating.  Three thoughts:

  • The GP History pane stores the state of a tool.  Each time the user runs your tool it'll show up in the History pane with its state.  For subsequent runs, they would open the tool from the history pane and it will open with the last parameters they used.  I use the History pane A LOT.

  • Run the tool within ModelBuilder.  Of course this requires your user to know ModelBuilder, but it acts much the same was as the History pane in that it remembers the state of the tool.

  • The last idea involves storing state in a file and opening/reading the file in your tools' updateParameters() method (Python toolbox) and initializeParameters() method (script tool).  Although it's discouraged, you can open/manipulate files as long as it doesn't affect performance. For simplicity, let's say there's only one state-keeping file for a project - that is, you don't allow the user to create and choose multiple state-keeping files.  For this you need a known stable location to create/write/read the file.  This ought to work:
aprx = arcpy.mp.ArcGISProject("CURRENT")
location = aprx.homeFolder

    I did something like this years ago in desktop.

You could get fancier by allowing the user to choose multiple state-keeping files.  This would require a new tool parameter to list the files and a catalog (such as a folder) to store the multiple files.     

Tool Validation topics: 

https://pro.arcgis.com/en/pro-app/latest/arcpy/geoprocessing_and_python/customizing-script-tool-beha...

https://pro.arcgis.com/en/pro-app/latest/arcpy/geoprocessing_and_python/customizing-tool-behavior-in...

 

 

View solution in original post

0 Kudos
5 Replies
Dale_Honeycutt
Frequent Contributor

Ha! You've discovered the stateless nature of GP Tools.  It can be infuriating.  Three thoughts:

  • The GP History pane stores the state of a tool.  Each time the user runs your tool it'll show up in the History pane with its state.  For subsequent runs, they would open the tool from the history pane and it will open with the last parameters they used.  I use the History pane A LOT.

  • Run the tool within ModelBuilder.  Of course this requires your user to know ModelBuilder, but it acts much the same was as the History pane in that it remembers the state of the tool.

  • The last idea involves storing state in a file and opening/reading the file in your tools' updateParameters() method (Python toolbox) and initializeParameters() method (script tool).  Although it's discouraged, you can open/manipulate files as long as it doesn't affect performance. For simplicity, let's say there's only one state-keeping file for a project - that is, you don't allow the user to create and choose multiple state-keeping files.  For this you need a known stable location to create/write/read the file.  This ought to work:
aprx = arcpy.mp.ArcGISProject("CURRENT")
location = aprx.homeFolder

    I did something like this years ago in desktop.

You could get fancier by allowing the user to choose multiple state-keeping files.  This would require a new tool parameter to list the files and a catalog (such as a folder) to store the multiple files.     

Tool Validation topics: 

https://pro.arcgis.com/en/pro-app/latest/arcpy/geoprocessing_and_python/customizing-script-tool-beha...

https://pro.arcgis.com/en/pro-app/latest/arcpy/geoprocessing_and_python/customizing-tool-behavior-in...

 

 

0 Kudos
sbrowneotogo
Emerging Contributor

Thanks for the guidance! I was also thinking about somehow loading parameters from a file but figured there must be a more graceful solution (it would seem there isn't!). Using the project filepath seems like a good way to go for a stable location.

0 Kudos
Dale_Honeycutt
Frequent Contributor

In scanning the doc, I found there are some caveats to the project directory

  • The user needs to save the project first, otherwise it goes to some default home location that'll be lost when they save for the first time
  • Then there's this:

Dale_Honeycutt_0-1711298608452.png

Seems like filePath is a better option than homeFolder

https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/arcgisproject-class.htm

 

0 Kudos
sbrowneotogo
Emerging Contributor

The aprx.filePath seems to return a path to an actual file like this (at least when working in an environment with an already saved project):

'C:\\test_project\\test_project.aprx'

whereas aprx.homeFolder returns an actual directory:

'C:\\test_project'

so I'm not sure how to use filePath - maybe just go up one level from the file itself to get its parent directory?

I have some logic to detect if the the parameter file exists, and if it doesn't I create it with default values, so if the user's effective homeFolder changes and they lose their current parameters, (for my purposes at least) it's not a big deal to start over again once with default values.

The potential homeFolder lock is a little more concerning - I'm just creating this tool for my own team, and I'm not anticipating releasing to a wider audience, but if I ever do I'll have to account for that. Very much appreciate the heads up!

0 Kudos
Dale_Honeycutt
Frequent Contributor

You could import Python's os.path module -- it has tons of methods for busting apart and constructing pathnames.  

0 Kudos