Seems like the latest version of arcpy has added a ParameterArray container for parameters! I can't seem to find the documentation for it, but it definitely adopts the string based indexing that I've been using for years now haha. Glad to see that this is finally being added officially, but it would be nice to have some documentation on how the parameters are accessed by string (name, displayName, either, case sensitive, etc.).
Additionally, is this something that I have to explicitly create? Or does the getParameterInfo function return this by default? It's not implemented in Python, so knowing if I need to explicitly cast to this would be nice. Here's my sample with the explicit construction:
from typing import Any
from arcpy import Parameter, ParameterArray
class Tool:
def getParameterInfo(self) -> ParameterArray:
return ParameterArray(
[
Parameter(name='my_parameter', displayName='My Parameter')
]
)
def execute(self, parameters: ParameterArray, messages: Any) -> None:
by_name = parameters['my_parameter']
by_display = parameters['My Parameter']
by_case_insensitive = parameters['MY_PARAMETER'] or parameters['my parameter']
Solved! Go to Solution.
If you look closer at the __init__.py file, the class is not defined at the module level but within a specific function, so it cannot be imported and used directly from ArcPy. If you want to interact with it, you have to go through the object returned from the function.
>>> import arcpy
>>> buffer_params = arcpy.GetParameterInfo("Buffer")
>>> type(buffer_params)
<class 'arcpy.GetParameterInfo.<locals>.ParameterArray'>
>>>
well... perhaps a different arcpy 3.7 !? (everything is updated)
Basic version, we don't get Advanced anymore for the MVP stuff. Enterprise? Mine is plain simple standalone
from arcpy import Parameter, ParameterArray
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: cannot import name 'ParameterArray' from 'arcpy' (C:\Arcpro_37\Resources\ArcPy\arcpy\__init__.py)ParameterArry doesn't even list with a dir(arcpy)
Hmmm, that's odd (I'm also using the Basic, tho I never got the MVP license and had to pay for a personal one). I only just now noticed it when my language server suggested it while importing Parameter:
I also get an import error when I actually import it, but the name exists in the __init__.py*i* file meaning that it's an interface for something in the C code. Possibly just accidentally published to the public API before it was implemented?
If you look closer at the __init__.py file, the class is not defined at the module level but within a specific function, so it cannot be imported and used directly from ArcPy. If you want to interact with it, you have to go through the object returned from the function.
>>> import arcpy
>>> buffer_params = arcpy.GetParameterInfo("Buffer")
>>> type(buffer_params)
<class 'arcpy.GetParameterInfo.<locals>.ParameterArray'>
>>>
That makes more sense, they must have just added that to the root typestub recently, as I've never seen it before.
Was kinda hoping that they had an official api for named parameter access that could be used in Python tools lol.
Edit:
I'm not sure if this is a new thing? It does seem to allow you to access by name. It also stores the named parameters as attributes on the list subclass... So if you have a name that collides with a list method it will overwrite it??
>>> # copy/paste of ParameterArray class from GetParameterInfo
>>> p = ParameterArray({'pop': arcpy.Parameter('pop')})
>>> p.pop()
TypeError: 'Parameter' object is not callable
Edit2:
So yes, it does seem that arcpy.gp.getParameterInfo just pulls the Parameter.name attribute...
>>> arcpy.gp.getParameterInfo('Clip_management')
{'in_raster': <Parameter object at ...>,
0: <Parameter object at ...>,
'rectangle': <Parameter object at ...>,
1: <Parameter object at ...>,
'out_raster': <Parameter object at ...>,
2: <Parameter object at ...>,
'in_template_dataset': <Parameter object at ...>,
3: <Parameter object at ...>,
'nodata_value': <Parameter object at ...>,
4: <Parameter object at ...>,
'clipping_geometry': <Parameter object at ...>,
5: <Parameter object at ...>,
'maintain_clipping_extent': <Parameter object at ...>,
6: <Parameter object at ...>}
Here's a minimal test case toolbox that creates a totally invalid ParameterArray (I'm leaving out any dunders, but if someone uses __getitem__ as a parameter name, it will make the ParameterArray totally unusable):
from arcpy import AddMessage, GetParameterInfo, Parameter
class Toolbox:
def __init__(self) -> None:
self.label = 'BustedToolbox'
self.alias = 'Busted Toolbox'
self.tools = [Tool]
class Tool:
def __init__(self) -> None:
self.label = 'Broken Tool'
def getParameterInfo(self) -> list[Parameter]:
return [
Parameter('pop','pop', parameterType='Optional'),
Parameter('append','append', parameterType='Optional'),
Parameter('clear','clear', parameterType='Optional'),
Parameter('copy','copy', parameterType='Optional'),
Parameter('count','count', parameterType='Optional'),
Parameter('extend','extend', parameterType='Optional'),
Parameter('index','index', parameterType='Optional'),
Parameter('insert','insert', parameterType='Optional'),
Parameter('remove','remove', parameterType='Optional'),
Parameter('reverse','reverse', parameterType='Optional'),
Parameter('sort','sort', parameterType='Optional'),
]
def execute(self, parameters: list[Parameter], messages: object) -> None:
params = GetParameterInfo()
AddMessage(str(params))
params.sort(key=lambda p: p.name)
AddMessage(str(params[0].value))Here's the version of this I've been using without issues for a couple years now. It's pretty barebones, but it doesn't overwrite instance attributes with Parameter objects (I use clear, sort, reverse, index, count, copy, and append as parameter names all the time!)
Joshua.. Good to know, I thought there were stripped down versions of arcpy to go with the stripped down license levels of Pro. The Basic level isn't much use for the stuff I want to work on (free or paid for).
Yeah, changing the licensing level from Advanced to Basic was a bit excessive. It is a trade-off going from Advanced to Standard, but going to Advanced to Basic really devalues the award/reward and personal use program.