Python Toolbox input parameter list: how to split name from group name?

772
9
Jump to solution
03-27-2023 04:12 AM
Manu
by
Occasional Contributor

I enabled multiple value input for some parameter in an ArcMap 10.8 Python Toolbox.

In my script, I can easily split the input received from the UI by applying .split(";") since the input values are separated by ";".

However, when the user selects a layer from the drop-down that is located within a group, each such value consists of the group name and the layer name, separated by "\". The problem: "\" is an escape character in Python. I cannot separate the layer name from the group name. I need the layer name, though, because I want to search the .mdx document for that name in order to get the full path to the layer on disc.

Is there some way to solve this?

I tried:

 

 

combined_name.split("\\")
combined_name.split(r"\\")
r"{0}".format(combined_name).split("\\")

 

 

where combined_name is the respective name extracted from the input variable. All these attempts were without success.

 

Edit: I tried the arcpy.GetParameter(0) suggestion with no success. This is the Toolbox I used to test it:

import arcpy as ap
# Toolbox
class Toolbox(object):
    def __init__(self):
        self.label = "Tool"
        self.alias = "Tool"
        # List of tool classes associated with this toolbox
        self.tools = [Tool]
class Tool(object):
    def __init__(self):
        self.label = "Tool"
        self.description = "Test GetParameter(0)."
        self.canRunInBackground = False
    def getParameterInfo(self):
        """Define parameter definitions"""       
        in_raster = ap.Parameter(
            displayName = "Input Raster",
            name = "Raster",
            datatype = ["GPRasterLayer", "DERasterDataset"],
            parameterType = "Required",
            direction = "Input",
            multiValue = True)
        params = [in_raster]
        return params
    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return True
    def updateParameters(self, params):
        return
    def updateMessages(self, params):
        return
    def execute(self, params, messages):
        rasters = ap.GetParameter(0)
        if rasters is None:
            ap.AddMessage("Parameter is of type None.")
        else:
            ap.AddMessage("Parameter is something other then None.")
        return

When I open the Tool dialogue and add some rasters to the list, I get the "Parameter is oy type None" message after running the tool.

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
Manu
by
Occasional Contributor

I found some solution (here, I added a condition to check whether the input is some file path that I don't want to mess up. The tool accepts selecting loaded layers from a drop-down as well as browsing files):

 

def replace_grouped(in_var):
    if not os.path.isfile(in_var):
        out = repr(in_var).strip("'").split("\\")[-1]
    else:
        out = in_var
    return out

 

or, in practice: Since somehow the ending \'" was introduced to some input variables but not others, I had to do the following

 

def replace_grouped(in_var):
    if not os.path.isfile(in_var):
        out = repr(in_var).strip("'").strip('"').strip("'").strip('"') \
            .split("\\")[-1]
    else:
        out = in_var
    return out

 

(very ugly, but I haven't found a better way to get rid of the trailing garbage yet.)

View solution in original post

0 Kudos
9 Replies
RichardHowe
Occasional Contributor III

Instead of grabbing the input as text, you could grab the item itself using:

arcpy.GetParameter()

Then use a for loop to access the layer properties

e.g.:

layernames = arcpy.GetParameter(0)

for l in layernames:
   arcpy.AddMessage(l.name)
0 Kudos
Manu
by
Occasional Contributor

Unfortunately, arcpy.GetParameter(0) returns "None" for my ArcMap MultiValue input parameter... I guess this only works in ArcGIS Pro.

0 Kudos
RichardHowe
Occasional Contributor III

This should work in ArcMap also. What Data Type do you have your multivalue input as? I've tried it with the option set to Layer and it works

0 Kudos
Manu
by
Occasional Contributor

I have some ["GPRasterLayer", "DERasterDataset"] datatype

0 Kudos
RichardHowe
Occasional Contributor III

So it would work with raster layers, but not with a raster dataset, as that can't have a "Layer Name" property anyway. It only has layer properties once it is inside of an MXD or your have cast it as a feature layer, but if that hasn't happened/isn't the case then you wouldn't have the issue with it being part of a group layer anyway, so perhaps you could code around that e.g. an if statement based on feature type then a for loop to access layer name for those inputs that support it.

0 Kudos
by Anonymous User
Not applicable

split() returns a list so you have to use an index to grab the item that you want.  Maybe you are doing this, but its not in your code example?

fc = combined_name.split("\\")[-1]
fc = combined_name.split(r"\")[-1]
fc = r"{0}".format(combined_name.split("\\")[-1])
0 Kudos
Manu
by
Occasional Contributor

True, it returns a list. However, it returns a list of a single element which is still the combined name...

0 Kudos
by Anonymous User
Not applicable

maybe try:

fc = str(combined_name).split("\\")[-1]
fc = str(combined_name).split(r"\")[-1]
fc = r"{0}".format(str(combined_name).split("\\")[-1])
Manu
by
Occasional Contributor

I found some solution (here, I added a condition to check whether the input is some file path that I don't want to mess up. The tool accepts selecting loaded layers from a drop-down as well as browsing files):

 

def replace_grouped(in_var):
    if not os.path.isfile(in_var):
        out = repr(in_var).strip("'").split("\\")[-1]
    else:
        out = in_var
    return out

 

or, in practice: Since somehow the ending \'" was introduced to some input variables but not others, I had to do the following

 

def replace_grouped(in_var):
    if not os.path.isfile(in_var):
        out = repr(in_var).strip("'").strip('"').strip("'").strip('"') \
            .split("\\")[-1]
    else:
        out = in_var
    return out

 

(very ugly, but I haven't found a better way to get rid of the trailing garbage yet.)

0 Kudos