Multivalue parameter as text in .pyt - reading in to imported module function

1209
2
Jump to solution
06-10-2014 08:55 AM
Tse_YangLim
New Contributor
I'm building a Python toolbox with a tool which calls specific functions from a custom module.

The main input parameter for this tool is a multivalue list of raster layers.

In the execute block of my tool, I use parameter[2].valueAsText to read in said parameter, as normal, and then feed it into a custom module function as follows:

output          = parameters[0].valueAsText input           = parameters[2].valueAsText function        = parameters[1].valueAsText functionname    = "Local" + function option          = parameters[3].valueAsText expression      = parameters[4].valueAsText  newGrid = getattr(localfuncs,functionname)(input,option,expression) newGrid.save(output)

In this case, I've tested it with one custom function (corresponding to 'functionname'):

def LocalMean(input,option,expression):     import arcpy     newGrid = arcpy.sa.CellStatistics(input,"MEAN")     return newGrid

The trouble is that the 'input' (multivalue read in as text) ends up being a semicolon-delimited string of file names, and the function in the custom module can't seem to convert it back to a list of raster layers for Cell Statistics to actually process. As a result I get this error:

Script failed because:      ERROR 000732: Input Raster: Dataset Development;Vegetation;Hydrology;Elevation does not exist or is not supported at this location:

I've tried reading in 'input' with .values instead of .valueAsText, so it comes in as a list, but then I get the error that 'cannot concatenate 'str' and 'list' objects' in the getattr line.

Any ideas what I can do about this?

I know this overall structure may seem unnecessarily complicated; but it's a key part of the bigger project. I'm not attached to specifically using getattr here, but solutions which preserve the basic structure, namely calling functions from a custom module using a string of the function's name, would be ideal. Thanks a lot!
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable
You need to split the string by semicolon to produce the list:

def LocalMean(input,option,expression):     import arcpy     newGrid = arcpy.sa.CellStatistics(input.split(';') ,"MEAN")     return newGrid


However, you may have issues with this because you are not getting the full paths to the data if you are using a raster layer parameter.  If this is the case you may want to add an extra parameter to grab the workspace of all rasters:

def LocalMean(ws, input, option, expression):     import arcpy, os     rasters = [os.path.join(ws, r) for r in input.split(';')]     newGrid = arcpy.sa.CellStatistics(rasters ,"MEAN")     return newGrid



I have to write tons of script tools for work, so I wrote this function a while back to fix input paramters from script tools.   People like to put spaces in path names too, so that can break the input string because extra quotes will be inserted in the semicolon delimited input list from multi-value types.  I usually pass arguments through this function before working with inputs in my script tools:

def fixArgs(arg, arg_type=list):     '''     fixes arguments from a script tool.  for example,      when using a script tool with a multivalue parameter,     it comes in as "val_a;val_b;val_c".  This function can     automatically fix arguments based on the arg_type.      Another example is the boolean type returned from a     script tool.  Instead of True and False, it is returned as     "true" and "false"      arg:      argument from script tool (arcpy.GetParameterAsText() or sys.argv[1]) (str)     arg_type: type to convert argument from script tool parameter      # Example:     >>> # example of list returned from script tool multiparameter argument     >>> arg = "val_a;val_b;val_c"     >>> fixArgs(arg, list)     ['val_a', 'val_b', 'val_c']     '''     if arg_type == list:         if isinstance(arg, str):             # need to replace extra quotes for paths with spaces             return map(lambda a: a.replace("'",""), arg.split(';'))         else:             return list(arg)     if arg_type == float:         try':             return float(arg)         except:             return 0     if arg_type == int:         try:             return int(arg)         except:             return 0     if arg_type == bool:         if str(arg).lower() == 'true' or arg in [True, 1]:             return True         else:             return False     if arg_type == str:         if arg in [None, '', '#']:             return ''     return arg

View solution in original post

0 Kudos
2 Replies
by Anonymous User
Not applicable
You need to split the string by semicolon to produce the list:

def LocalMean(input,option,expression):     import arcpy     newGrid = arcpy.sa.CellStatistics(input.split(';') ,"MEAN")     return newGrid


However, you may have issues with this because you are not getting the full paths to the data if you are using a raster layer parameter.  If this is the case you may want to add an extra parameter to grab the workspace of all rasters:

def LocalMean(ws, input, option, expression):     import arcpy, os     rasters = [os.path.join(ws, r) for r in input.split(';')]     newGrid = arcpy.sa.CellStatistics(rasters ,"MEAN")     return newGrid



I have to write tons of script tools for work, so I wrote this function a while back to fix input paramters from script tools.   People like to put spaces in path names too, so that can break the input string because extra quotes will be inserted in the semicolon delimited input list from multi-value types.  I usually pass arguments through this function before working with inputs in my script tools:

def fixArgs(arg, arg_type=list):     '''     fixes arguments from a script tool.  for example,      when using a script tool with a multivalue parameter,     it comes in as "val_a;val_b;val_c".  This function can     automatically fix arguments based on the arg_type.      Another example is the boolean type returned from a     script tool.  Instead of True and False, it is returned as     "true" and "false"      arg:      argument from script tool (arcpy.GetParameterAsText() or sys.argv[1]) (str)     arg_type: type to convert argument from script tool parameter      # Example:     >>> # example of list returned from script tool multiparameter argument     >>> arg = "val_a;val_b;val_c"     >>> fixArgs(arg, list)     ['val_a', 'val_b', 'val_c']     '''     if arg_type == list:         if isinstance(arg, str):             # need to replace extra quotes for paths with spaces             return map(lambda a: a.replace("'",""), arg.split(';'))         else:             return list(arg)     if arg_type == float:         try':             return float(arg)         except:             return 0     if arg_type == int:         try:             return int(arg)         except:             return 0     if arg_type == bool:         if str(arg).lower() == 'true' or arg in [True, 1]:             return True         else:             return False     if arg_type == str:         if arg in [None, '', '#']:             return ''     return arg
0 Kudos
Tse_YangLim
New Contributor
The semicolon split did the trick! Thanks a lot!
0 Kudos