Wednesday, October 20, 2010

Using custom toolboxes in ArcToolbox

I don't care for the batch processor in ArcGIS. As far as I can tell, I need to manually type in the filenames for each of my zillion output files. Frankly, that's close to useless. Someone at ESRI should take a look at the batch processor in Erdas Imagine (which I haven't used in years, but I remember it was great). It allowed you to set up variables and automate things like output names.

So what does this have to do with custom toolboxes? Well, I wrote a Python script to do a bunch of stuff to a data set and created a tool that used my script. But my ultimate goal was to process a whole bunch of files, so then I created another tool that looped through all of the files in a directory, automatically created output names, and called the original tool to do the processing. This way I only needed to maintain the code in one place but had a tool that worked on just one file as well as one that could handle a ton of them at once.

I put both tools in a custom toolbox, but the batch tool couldn't find the original tool because the toolbox hadn't been imported. This makes sense to me when running a script outside of ArcMap, since the toolbox isn't loaded by default. But it seems to me that if a tool is running, the toolbox that it lives in should be automatically loaded. But it's not. And what's even weirder is that ListToolboxes() and ListTools() find the toolbox and tools in question, but they can't be used until ImportToolbox() is called.

That's fine, except ImportToolbox() takes a path to a toolbox file. I can hard code that in for myself, but what if I give the toolbox to a coworker? Unless they use the exact same directory structure as I do then the tool is broken. I don't want to make them go in and edit the script (that's just asking for trouble!). I couldn't find any way to solve this problem using the arcpy functions provided by ESRI. It would be nice if they had a way to get info, like filename, about a toolbox found with ListToolboxes(), but either I'm blind or it's not there.

Assuming that the script and the toolbox live in the same directory, there is a simple solution to the problem, however:

arcpy.ImportToolbox(os.path.join(os.path.split(sys.argv[0])[0], 'toolbox.tbx'))

This gets the path of the currently executing script (sys.argv[0]), gets the directory of that (os.path.split()[0]) and then appends the filename of the toolbox to that with os.path.join(). That is then passed to ImportToolbox() and everything is good. Until someone renames the .tbx file, that is...