[GIS] Accessing multivalue output parameter from Python script in ModelBuilder in ArcGIS Desktop

arcgis-10.0arcpymodelbuilder

How do I access a multivalue output parameter from a python script in modelbuilder, in ArcGIS 10.0?

That is, I have a python script that loops through several input layers (working through a script tool in a toolbox), performing a number of tasks and finally outputting a final layer. There is one output layer for each input layer. The number of input layers is typically 5, but not always. I have seen Using multivalue output parameter with ArcPy?

My entire script is too long to post, so I have posted a pared down version at the end of my post.

You will see that my script currently creates output parameters (feature layers) as part of the loop, using an incrementing number variable as the output parameter number. The script works fine as long as I know how many input layers I will be looping through and I can set up the output parameters of the attached toolbox tool appropriately.

But I need to have a tool(s) that don't know how many inputs there will be. I see from the referenced link how to set up a semicolon-delimited string as the output parameter, but I can't figure out how to do anything with it in modelbuilder. I also setup a boolean output parameter that simply shows that the script has run, in case the number of output layers is fewer than what I have set up for the tool–but I would like something better than that. I thought all the new iterators and other new modelbuilder-specific tools were supposed to be for things like this, but I can't get it to work. Of course, I could be setting up the tool parameters incorrectly, using the modelbuilder iterators incorrectly, I don't know.

Does anybody know how to do this?

Can you show me an example?

The link I referred to doesn't actually show any examples of the ModelBuilder as recipient of such an output parameter (the semicolon-delimited string) or describe what to do.

# IMPORT MODULES  
import arcpy, os, sys, string, traceback, datetime  

# SCRIPT ARGUMENTS  
# Select layer  
inSelect = arcpy.GetParameterAsText(0)  
# Input layers  
inLayers = string.split(arcpy.GetParameterAsText(1), ";")  
# Output workspace  
outFolder = arcpy.GetParameterAsText(2)  

# OTHER FRONT STUFF

try:
    # SET VAR FOR INITIAL OUTPUT PARAMETER NUMBER
    outputParam = 4
    # SET VAR FOR COMPLETION OUTPUT PARAMETER
    bComplete = False
    # CREATE LIST FOR INTERMEDIATE DATA TO BE DELETED DURING FINALLY
    intermediateData = []
    # LOOP THROUGH INPUT LAYERS.
    for lyr in inLayers:

        # SELECT FEATURES

        # PROJECT

        # BUFFER

        # MERGE

        # CREATE LAYER
        # Create virtual layer
        layerName = lyr + prjLayernameSuffix
        virtualLayer = arcpy.MakeFeatureLayer_management(outFC, layerName)
        # Create layer on disk - required for arcpy.mapping.Layer
        layerFilename = layerName + ".lyr"
        layerPath = os.path.join(outFolder, layerFilename)
        arcpy.SaveToLayerFile_management(virtualLayer, layerPath, "RELATIVE")
        # Find layer to symbolize from - some of this is left out from actual script
        symbolLayerName = hcatype + "_sample_buffers.lyr"
        symbolLayer = arcpy.mapping.Layer(os.path.join(tooldataPath, symbolLayerName))
        # Create map layer from layer file - must use complete path
        mapLayer = arcpy.mapping.Layer(layerPath)
        # Symbolize map layer
        arcpy.mapping.UpdateLayer(df, mapLayer, symbolLayer, True)
        mapLayer.transparency = outputLayerTransparency
        # Add map layer to current map
        arcpy.mapping.AddLayer(df, mapLayer)
        # Save a layer file with FC in case you want to re-use the layer
        arcpy.SaveToLayerFile_management(mapLayer, layerPath, "RELATIVE")

        # CLEAR SELECTION

        # SET OUTPUT PARAMETER AND INCREMENT PARAMETER NUMBER
        arcpy.SetParameter(outputParam, mapLayer)
        outputParam += 1

    # SET COMPLETION OUTPUT PARAMETER
    bComplete = True
    arcpy.SetParameter(3, bComplete)

    # REFRESH
    arcpy.RefreshActiveView()
    arcpy.RefreshTOC()
    mxd.save()

except:
    # SET COMPLETION OUTPUT PARAMETER
    arcpy.SetParameter(3, bComplete)
    tb = sys.exc_info()[2]
    tbinfo = traceback.format_tb(tb)[0] 
    pymsg = tbinfo + "\n" + str(sys.exc_type)+ ": " + str(sys.exc_value) 
    arcpy.AddError("Python Messages: " + pymsg + " GP Messages: " + arcpy.GetMessages(2))

finally:
    # Delete vars and intermediate data
    for dataObj in intermediateData:
        if arcpy.Exists(dataObj):
            arcpy.Delete_management(dataObj)
    del inSelect, inLayers, prjSpatRef, outFolder
    # Other appropriate deletions are left out for clarity of example
    del layerName, virtualLayer, layerFilename, layerPath, mapLayer

Best Answer

The Setting script tool parameters ESRI Help files explains that the multivalue input parameter returns a semi-colon separated string (as you've noted). In order to get a list rather than a semi-colon string you use the split method.

inString = arcpy.GetParameterAsText(1)
inLayers = inString.split(";")

Once you have your new list, you can determine how many elements it contains with len().

outputParam = len(inLayers)

Now every time you run the script tool, outputParam will be set to the # of elements in the list (dynamic, Yay!)

Related Question