1

I am writing a function to update the value of some features inside a feature class after selecting them with arcpy.SelectLayerByLocation_management().

everything works fine in Pro but when I move to standalone script (that does not reference a specific aprx project) I am having issues.

in Pro I used

desc = arcpy.Describe(inFc)
if desc.FIDSet:

to check if some features was selected by the function SelectLayerByLocation and if so I update the values with a cursor. In a standalone script this method is not available (DescribeData: Method FIDSet does not exist). someone say to use arcpy.GetCount_management(), but this method returns the total number of features in the FC is no feature is selected; this way my cursor will update everything ignoring the SelectLayerByLocation step.

ChatGPT says to create a new layer with the selection made by SelectLayerByLocation but still if 0 features have been selected the newly created temp layer will contain all the features in the main Feature class.

is there a way to solve my problem without referencing the layers in a aprx project but by working on a gdb as I am doing now?

this is my function that works in PRO but not in standalone

def checkFilling(inFc, mode, intersectFc, timeFile):    
    try:

        # Select only gaps contained in the coverage map
        arcpy.SelectLayerByLocation_management(inFc, "WITHIN", intersectFc)

        # Get the selected feature count
        desc = arcpy.Describe("inFc_layer")

        if desc.FIDSet:
            # Update the end date for selected features
            with arcpy.da.UpdateCursor(inFc, ["end_date"]) as cursor:
                for row in cursor:
                    # Update the field value as needed
                    row[0] = timeFile
                    cursor.updateRow(row)
            print("Update completed successfully.")
        else:
            print("No features selected.")
    except Exception as e:
        print("An error occurred: {}".format(str(e)))
 

timeFile = "25/12/2023"
checkFilling("layerToUpdate", "WITHIN", "layerThatMightContainFeatures", dateVariable)
3
  • 1
    Use make feature layer first and getSelectionset after
    – FelixIP
    Commented Dec 21, 2023 at 8:46
  • You can also call get count on the feature class without selection. Assign the arcpy.SelectLayerByLocation_management() call to a variable, selection for example. The result object has a count of the selected features, you can access with selection[2] (check the Derived Outputs section of the tool documentation). Although the docs say a Long is returned for the selection count, I'm pretty sure its a string so you may need to cast to int. You can then say if selection count is less than original count, you have a subset. Commented Dec 21, 2023 at 9:20
  • Starting with ArcGIS Pro 3.2, the ArcPy Data Access cursors support spatial filters and expressions directly, so you no longer have to rely on Select Layer By Location first.
    – bixb0012
    Commented Dec 21, 2023 at 15:23

2 Answers 2

3

The FIDSet returns the selected features of a layer, but if you are working directly on a featureclass, there is no such thing as a selected feature. It should probably work if you create a featurelayer first, and then select some features in that layer.

However, there is no need to do that. You can skip the check for FIDSet altogether, and use a where clause in the UpdateCursor. That is, if you don't want to update all features, but only a subset.

When selecting by location, you can't use just the UpdateCursor, but must use SelectByLocation first. The good thing is that SelectLayerByLocation already returns a layer, so there is no need for MakeFeatureLayer. Here's an example:

layer = arcpy.management.SelectLayerByLocation(inFc, "WITHIN", intersectFc)

desc = arcpy.da.Describe(layer)

arcpy.AddMessage(len(desc["FIDSet"]))
1
  • Hi Berend thanks for your reply. I thought about that but I am not sure how to "link" the where clause to the result of the arcpy.SelectLayerByLocation_management.
    – fed
    Commented Dec 21, 2023 at 11:34
1

If you take a look at the example in the documentation for Select Layer By Location, there is an example that should help you.

Try this:

def checkFilling(inFc, mode, intersectFc, timeFile):    
    try:
        select_layer = arcpy.SelectLayerByLocation_management(inFc, "WITHIN", intersectFc)
        select_count = int(arcpy.GetCount_management(select_layer)[0])

        if select_count:
            with arcpy.da.UpdateCursor(select_layer, ["end_date"]) as cursor:
                for row in cursor:
                    row[0] = timeFile
                    cursor.updateRow(row)
            print("Update completed successfully.")
        else:
            print("No features selected.")
    except Exception as e:
        print("An error occurred: {}".format(str(e)))

Note two specific changes:

  1. You need to use the output of the SelectLayer function. In Pro, this is easy to find: usually it just appends _layer to your layer name, but you're picking it for forward operations from a list anyway. Where this goes in arcpy is a little more complicated because the context is different. The function makes it easy for you by returning a result object with the layer it created.
  2. If you want to update selections, as opposed to the underlying original source FC, you need to use this result layer in your cursor operation. Otherwise you're updating all items. Alternately, you could use a WHERE clause on the UpdateCursor, but that's probably unnecessary complexity.

Also, you could replace this:

select_count = int(arcpy.GetCount_management(select_layer)[0])

with this:

select_count = int(select_layer[2])

The result object returned from SelectLayer has multiple values, one of which is the selection count. When using the result as a layer in a future arcpy call, it is implicitly coerced into just the layer name so it works. I personally prefer an explicit GetCount call, because explicit is better than implicit and I've found that the return values for arcpy functions aren't always quite stable across different versions. The direct access to the result object, the implicit way, is probably more performant so maybe use that if you have to do this tens of thousands of times.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.