Using MakeFeatureLayer in ArcPy?

by Squinney   Last Updated August 13, 2019 21:22 PM

I am trying to add a feature layer to my map document as the output from my python script. The goal is to limit the number of fields in the attribute table to a pre-defined list. I am able to add the feature layer to my map document, but all of the fields display. However, when I use arcpy.Describe() on the layer my script added to the map, the Describe results show the desired field subset. I can't figure out what is going on.

def makeFeatureLayer(outputFC, fieldTable, input_FC, input_ID, mapLayers):
    outputFeatureLayer = "{0}".format(os.path.basename(outputFC))
    subField = "{0}".format(arcpy.Describe(outputFC).subtypeFieldName)
    displayFieldList = [input_ID, subField]
    with arcpy.da.SearchCursor(fieldTable, ["layer_name", "Attribute"]) as cursor:
        for row in cursor:
            if "{0}".format(row[0]) == "{0}".format(os.path.basename(input_FC)):
                displayFieldList.append("{0}".format(row[1]))

    outputFieldList = arcpy.ListFields(outputFC)
    fieldInfo = "{0}".format(input_ID) + " " + "{0}".format(input_ID) + " " +  "VISIBLE" + " " + "NONE;" + "{0}".format(subField) + " " + "{0}".format(subField) + " " +  "VISIBLE" + " " + "NONE;" 
    for f in outputFieldList:
        if f.name in displayFieldList:
            fieldInfo = fieldInfo + f.name + " " + f.name + " " + "VISIBLE" + " " + "NONE;"
        else:
            fieldInfo = fieldInfo + f.name + " " + f.name + " " + "HIDDEN" + " " + "NONE;"

    arcpy.management.MakeFeatureLayer(outputFC, outputFeatureLayer, "", "", fieldInfo)

    mapLayers.append(outputFeatureLayer)

    del subField, displayFieldList, outputFieldList, fieldInfo

def updateMap(mapLayers):
    mxd = arcpy.mapping.MapDocument("CURRENT")
    dataFrame = arcpy.mapping.ListDataFrames(mxd)[0]
    for layer in mapLayers:
        arcpy.mapping.AddLayer(dataFrame, arcpy.mapping.Layer(layer), "TOP")
        arcpy.RefreshActiveView()
        arcpy.RefreshTOC()
    del mxd, dataFrame

I tried leaving out arcpy.mapping.Layer in case this was undoing the fieldInfo settings/field selection, and just trying to add the feature layer to the map document directly, but that generates an assertion error. Also, if I run the code it actually results in two new layers to my map document: a visible layer that shows all the fields, and the original output of the MakeFeatureLayer tool, but it is not visible and cannot be added to the map display unless I export it to a .lyr file first.

Any ideas?

I was able to get MakeFeatureLayer to work from the Python window just fine. I tried to use ListLayers() and use that to get at the feature layer after creating it, but that didn't work either.


I can sort of work around this by saving the results of MakeFeatureLayer to a .lyr file, but this is not ideal as I do not want to write anything extra to disk just for the field display. When I add the .lyr file to the map document, though, it works the way I intend and only shows the subset of fields.

Tags : arcpy layers


Answers 1


Working with layers can indeed be tricky, with the multiple steps of adding one to your map. Also confusion can arise with the in memory layer created by arcpy.MakeFeatureLayer_management and the mapping layer you add to your map via arcpy.mapping.AddLayer usually having the same name. These two 'layers' are similar objects but are not, in fact, the same, and having both the in memory layer and the mapping layer to deal with at the same time can cause frustration.

I've created a simplified code based off what you provided. It won't produce quite the same results as yours, as you add multiple layers from a list. Mine just adds one. But I hope that showing the steps to add a single layer and turn off undesired fields can still help.

In my script, I generate the list of fields to keep visible with roughly the same code you provide. I then create an in memory layer file, and add "_templyr" to the end of its name to distinguish it from the mapping layer that will later be added to the map. I then create the mapping layer object, and rename it to remove the "templyr" designation. After I add this mapping layer to the map, I delete the in memory layer. I then work with a fieldInfo object to set fields not in my displayFieldList to hidden.

I can't test the code, so there may need to be a little cleanup from a messup on my part.

subField = arcpy.Describe(outputFC).subtypeFieldName
displayFieldList = [input_ID, subField]
with arcpy.da.SearchCursor(fieldTable, ["layer_name", "Attribute"]) as cursor:
    for row in cursor:
        if row[0] == os.path.basename(input_FC):
            #List of fields to show
            displayFieldList.append(row[1]) 

outputFeatureLayer = os.path.basename(outputFC) + "_templyr"
#Create in memory layer with 'templyr' as designation
arcpy.MakeFeatureLayer_management (outputFC, outputFeatureLayer) 

mxd = arcpy.mapping.MapDocument("CURRENT")
dataFrame = arcpy.mapping.ListDataFrames(mxd)[0]

#Create mapping layer
lyr = arcpy.mapping.Layer(outputFeatureLayer)

#Remove "_templyr" from mapping layer name
lyr.name = outputFeatureLayer.replace ("_templyr", "")

#Add mapping layer to map
arcpy.mapping.AddLayer(dataFrame, lyr, "TOP")

#delete layer in memory to prevent confusion
arcpy.Delete_management (outputFeatureLayer)

#Get field info object
fieldInfo = arcpy.Describe (lyr).fieldInfo 

#Check if field is in list, if not set to hidden
index = 0
while index < fieldInfo.count:
    fldName = fieldInfo.getFieldName(index)
    if not fldName in displayFieldList:
        fldInfo.setVisible (index, "HIDDEN")
    index += 1

arcpy.RefreshActiveView()
arcpy.RefreshTOC()
del mxd, dataFrame

I hope this helps a little!

Emil Brundage
Emil Brundage
December 23, 2014 08:12 AM

Related Questions


Updated March 04, 2016 01:09 AM

Updated July 09, 2017 14:22 PM

Updated August 16, 2015 17:09 PM

Updated May 10, 2016 08:09 AM

Updated December 08, 2016 08:09 AM