4

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

3 Answers 3

6

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!)

3
  • Thanks, Roy. Yes, this is true. My question is what do you do with this output parameter result in modelbuilder to iterate through it? I am guessing I was not very clear on my question. I see how this output parameter works if nested into another python script; my question is how to use it in modelbuilder. I can't figure out how to use the new iterator and modelbuilder-only tools to make such a thing work.
    – Ruth
    Aug 24, 2012 at 17:59
  • Looking at the script, it appears the outputParam var is being used to create a script Parameter than can insert the layer into the map (without the whole script I can't tell for sure). In all honesty, I find Modelbuilder to be convoluted and more difficult to work with than straight Python. I'd be happy to work with you on a Python solution, but I've only ever used Modelbulider for diagraming my analysis.
    – Roy
    Aug 24, 2012 at 18:10
  • 1
    I agree with you Roy, but our company likes to make sure our scripts will work as script tools in modelbuilder too--which means they have to have functioning output parameters. It is handy when someone wants to do something quickly without programming.
    – Ruth
    Aug 24, 2012 at 21:27
2

To create a multivalue parameter in ModelBuilder:

  1. Create Variable (FeatureLayer type, Model Parameter)
  2. Right-click > Properties
  3. Under the General tab, change 'This variable contains:' to 'A list of values'

I believe you'll need to change your output parameter to a semicolon delimited list as the other post explains.

1
  • I will try using a created variable like this rather than the one that pops in when I drag over the script tool. I will post the results.
    – Ruth
    Aug 24, 2012 at 21:24
2

You are not building the output multivalue parameter correctly, only setting it to one output with each iteration, so at the end you only have one item being output (the last one).

To do this correctly, first initialize an empty list outside of the loop. Then within the loop, add each output to the list. Finally, after the loop, convert the list to a semicolon-delimited string (using ';'.join(yourListVariable)) and set the output parameter to that string.

As for using it in ModelBuilder, there are tools that accept multiple inputs that should work directly with the multivalue output of your script tool. For other tools that only accept single inputs, you can use model iterators. We need to know what you're trying to do in ModelBuilder to help you on that front.

4
  • Thanks, blah (have to smile at your handle). I guess I have not put this very clearly. I know how to do the python. The example I used shows single value output parameters, but I know how to do the multivalue output parameters. Perhaps I should have just left out the python, since that is not my question. I just thought people would want to see what I was doing.
    – Ruth
    Aug 24, 2012 at 21:10
  • My question is whether someone has an example to show of iterating in a model, using the output from a looping python script. This being whether the output parameter(s) (from the python script) is a single multi-value semi-colon-delimited string or multiple single-value output parameters (such as my example) being collected with a modelbuilder-only tool and iterated in that way. I can't find an example from someone who has actually done this. I have been trying myself, and can't get it to work with any combination of modelbuilder tools--hence my post. I hope this clarifies things a little.
    – Ruth
    Aug 24, 2012 at 21:20
  • 1
    I would use the Iterate Multivalue iterator. See Examples of using iterators in ModelBuilder.
    – blah238
    Aug 25, 2012 at 5:13
  • 1
    Oh, you also probably will want to nest the tools you need to run multiple times in a submodel, along with the iterator. Since you only want your script tool to run once, it needs to be in the outer model. See the "Advanced use of model iterators" section on this page: Integrating a model within a model
    – blah238
    Aug 25, 2012 at 5:18

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.