layer object vs. layer name

3014
3
10-05-2017 11:46 AM
GeorgeRiner
New Contributor III

I don't understand when an input argument to an arcpy function that says it takes a layer as an input but it really only works when I give it the name of the layer. Specifically: I use the arcpy.mapping.ListLayers() function to get a list of all the 'layers' in my mxd. I then search through this list to find the layer for which the .name value of the layer I'm interested in. I then copy this layer object out of the list returned by ListLayers(). I assume that what I have is a layer in the sense of what's documented on this page: Layer—Help | ArcGIS Desktop 

I then read the documentation for the SelectLayerByAttribute_management() at: Select Layer By Attribute—Help | ArcGIS Desktop 

and it looks like it says that it takes a 'Layer' as it's first argument.  So I call arcpy.SelectLayerByAttribute_management() handing it my layer object (from above) and the second argument of "CLEAR_SELECTIONS".  The error message I get back is "ERROR 000732: Layer Name or Table View: Dataset GPL0 does not exist or is not supported". 

so, it seems I just called a function that wants a layer as its first argument and I hand it a layer object that arcpy handed to me, and the function barks.  So I try using the string value of the layer name as the first argument and now the function works like a charm! So, if a string value of the layer's name that I want to clear selections for is what the function wants, then why doesn't the documentation say the the first argument is a string value, instead of a layer object?

Python snippet:

mxd = arcpy.mapping.MapDocument("CURRENT")

main_frames = arcpy.mapping.ListDataFrames(mxd,"Layers")

main_frame = main_frames[0]

main_layers = layers = arcpy.mapping.ListLayers(mxd,"*",main_frame)

for lay in main_layers:

   if lay.name == 'Report Polygons':

      rpolys = lay

rpolys.isFeatureLayer         # this is 'True'

rpolys.isBroken               # this is 'False'

rpolys.isGroupLayer           # this is 'False'

rpolys.serviceProperties['Is_Geodatabase']         # this has the value 'true'

arcpy.SelectLayerByAttribute_management(rpolys,"CLEAR_SELECTION")       # this fails

arcpy.SelectLayerByAttribute_management(rpolys.name,"CLEAR_SELECTION")  # this gives me a <Result>

This seems to be the case for many of the arcpy functions that claim to take a 'Layer' as an input argument - all they really want is a string that contains the name of the layer.

Is it a fools errand to search my mxd for the layer I want to use when it appears that functions like SelectLayerByAttribute_management() will do it for me?

3 Replies
DanPatterson_Retired
MVP Emeritus

I agree with the sometimes conflicting information.  I rapidly learned to use the code examples for guidance rather than the tabular description of parameters.  I think part of the problem lies in the reluctance to name the parameters directly (ie layer versus layername). It is no consolation but you will eventually get used to it

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

I discuss this a bit in a blog post:  /blogs/tilting/2014/08/19/whats-in-a-data-type-when-featureclass-string .  The way I usually approach it is that the documentation for native ArcPy functions, like arcpy.mapping.ListLayers(), is much truer to the data type the function, method, or property needs while the documentation for Geoprocessing functions, like arcpy.SelectLayerByAttribute_management,  tends to state the type of object the string name you pass refers back to.  The documentation is fairly consistent within each group/type of ArcPy functions, it just isn't consistent between the two groups/types themselves.

I agree with Dan, you get used to it, but I still think it is sloppy on Esri's part.

GeorgeRiner
New Contributor III

Taking this another step then ...

I was trying to make interactive debugging possible while developing an arcpy tool. (interspersing my code with bits of arcpy.AddMessage() to output variable values is so ... 1970's; i.e. lame.) It is apparently well known that running the python debugging IDE takes you away from the current map document in which the tool is invoked.  I.e., references to layers by only their name works fine if the current map document is available but not when debugging because there is no 'current map document' available.

Is there some mysterious undocumented 'environment'-like value that indicates what the current map document is?  If I could set this, then references to layers by namestring could work.  But I can't find a way to set this. 

I was hoping that if a tool says it takes a 'layer' as input, that it really meant a layer object and that object could refer to a layer in the current map document or a layer object obtained from an 'external' map document. But arcpy tools that take layer names apparently only search for those names in the 'current' map document; and when I'm in the interactive debugger then there is no current map document.  This is dumb. Why can't I just set the current map document and get a working context during debugging??

0 Kudos