Select to view content in your preferred language

update cursor fails to work

482
8
10-30-2024 08:20 AM
StuartMoore
Frequent Contributor

so this is to check if any annotation overlaps and if it does it rotates one by 90 degrees

 

this just loops through the features and works fine

with arcpy.da.UpdateCursor(fc, ["objectid", "FeatureID","Angle" ,"SHAPE@", "SHAPE@X", "SHAPE@Y","LEGACY_TABLE_NAME"],"objectid in (4007789,4007788,4007787,4007786,4007791,4007790)") as Cur:
    for row in Cur:

        # read in the data

        print row[0]

        SA_Filter = "OBJECTID = {0}".format(row[0])
        try:
            arcpy.management.SelectLayerByAttribute(fc, "NEW_SELECTION", SA_Filter)
            annocount = arcpy.management.GetCount(fc)
            print "tmp count: {0}".format(annocount[0])
            if int(annocount[0]) == 1:
                print "selected one anno"

                arcpy.management.SelectLayerByLocation(fc, "INTERSECT", fc, "", "NEW_SELECTION")
                tmpcount = arcpy.management.GetCount(fc)
                print "tmp count: {0}".format(tmpcount[0])
                if int(tmpcount[0]) >= 2 and int(tmpcount[0]) < 74:
                    print "more than 1"
                    row[2] = float(row[2]) + 90
        except:
            print "Error"

StuartMoore_0-1730301393285.png

but when i add in a simple update to a text field it fails

with arcpy.da.UpdateCursor(fc, ["objectid", "FeatureID","Angle" ,"SHAPE@", "SHAPE@X", "SHAPE@Y","LEGACY_TABLE_NAME"],"objectid in (4007789,4007788,4007787,4007786,4007791,4007790)") as Cur:
    for row in Cur:

        # read in the data

        print row[0]

        SA_Filter = "OBJECTID = {0}".format(row[0])
        try:
            arcpy.management.SelectLayerByAttribute(fc, "NEW_SELECTION", SA_Filter)
            annocount = arcpy.management.GetCount(fc)
            print "tmp count: {0}".format(annocount[0])
            if int(annocount[0]) == 1:
                print "selected one anno"

                arcpy.management.SelectLayerByLocation(fc, "INTERSECT", fc, "", "NEW_SELECTION")
                tmpcount = arcpy.management.GetCount(fc)
                print "tmp count: {0}".format(tmpcount[0])
                if int(tmpcount[0]) >= 2 and int(tmpcount[0]) < 74:
                    print "more than 1"
                    row[2] = float(row[2]) + 90
                    row[6] = "updated"
                    Cur.updateRow(row)
        except:
            print "Error"

StuartMoore_1-1730301572174.pngStuartMoore_2-1730301588452.png

 

0 Kudos
8 Replies
CodyPatterson
MVP Regular Contributor

Hey @StuartMoore 

In your try except error, can you add a message that prints the error inside? It may be more descriptive and point out which part is causing an issue.

except Exception as e:
   print(f"Error with message: {e}")

From the surface, it's slightly difficult to see what's going on, especially since the error is saying the select by attribute is causing the issue. I would also print SA_Filter to see what it's printing.

Cody

0 Kudos
StuartMoore
Frequent Contributor

Hi @CodyPatterson 

this is what i get: 

StuartMoore_0-1730306670750.png

i think the issue is with this line as it works in terms of selecting the features by their objectid and also the select by location part.

Cur.updateRow(row)

 

i'm running this in Desktop 10.2.1 on a versioned dataset. i'm very confident that it was working yesterday but today its being a pain...

i've used similar update cursors and its worked but this time after the first feature it seems to loose connection with the database as the features disappear from the map and this pops up:

StuartMoore_1-1730307197378.png

 

0 Kudos
BrandonMcAlister
Frequent Contributor

@StuartMoore 

I think the issue lies with the fact that you are using an update cursor as a search cursor. I would create a search cursor to get object ids and evaluate their position and information with that. Then when I run into a feature that needs to be turned create an update cursor with a where clause that updates that object id. 

Thanks,
Brandon
0 Kudos
StuartMoore
Frequent Contributor

Hi @BrandonMcAlister 

thanks i tried that and it still failed, i even recreated the data and re-ran it incase the data had been corupted

 

with arcpy.da.SearchCursor(fc, ["objectid", "FeatureID","Angle" ,"SHAPE@", "SHAPE@X", "SHAPE@Y","LEGACY_TABLE_NAME"],"objectid in (4011345,4011328,4011327,4011326,4011325,4011324,4011323,4011346)") as Cur:
    for row in Cur:

        # read in the data

        print row[0]

        SA_Filter = "OBJECTID = {0}".format(row[0])
        print SA_Filter
        try:
            arcpy.management.SelectLayerByAttribute(fc, "NEW_SELECTION", SA_Filter)
            annocount = arcpy.management.GetCount(fc)
            print "tmp count: {0}".format(annocount[0])
            if int(annocount[0]) == 1:
                print "selected one anno"

                arcpy.management.SelectLayerByLocation(fc, "INTERSECT", fc, "", "NEW_SELECTION")
                tmpcount = arcpy.management.GetCount(fc)
                print "tmp count: {0}".format(tmpcount[0])
                if int(tmpcount[0]) >= 2 and int(tmpcount[0]) < 74:
                    print "more than 1"
                    with arcpy.da.UpdateCursor(fc, ["objectid", "FeatureID","Angle" ,"SHAPE@", "SHAPE@X", "SHAPE@Y","LEGACY_TABLE_NAME"],"objectid = {0}".format(row[0])) as UPDCur:
                        for upd in UPDCur:
                            print "entered Update cursot"
                            upd[2] = float(upd[2]) + 90
                            upd[6] = "te22st"
                            UPDCur.updateRow(upd)
        except Exception as e:
            print "Error with message: {0}".format(e)

 

StuartMoore_0-1730365975858.png

 

0 Kudos
StuartMoore
Frequent Contributor

but oddly if i reconcile my session and refresh the map it has updated the first one

StuartMoore_1-1730366196484.png

i'm thinking the issue is the arcfm session side

 

0 Kudos
StuartMoore
Frequent Contributor

i change it to use the field calculator instead of the update cursor, it works but the downside is its significantly slower 😔

with arcpy.da.SearchCursor(fc, ["objectid", "FeatureID","Angle" ,"SHAPE@", "SHAPE@X", "SHAPE@Y","LEGACY_TABLE_NAME"],"objectid in (4011345,4011328,4011327,4011326,4011325,4011324,4011323,4011346)") as Cur:
    for row in Cur:

        # read in the data

        print row[0]

        SA_Filter = "OBJECTID = {0}".format(row[0])
        print SA_Filter
        try:
            arcpy.management.SelectLayerByAttribute(fc, "NEW_SELECTION", SA_Filter)
            annocount = arcpy.management.GetCount(fc)
            print "tmp count: {0}".format(annocount[0])
            if int(annocount[0]) == 1:
                print "selected one anno"

                arcpy.management.SelectLayerByLocation(fc, "INTERSECT", fc, "", "NEW_SELECTION")
                tmpcount = arcpy.management.GetCount(fc)
                print "tmp count: {0}".format(tmpcount[0])
                if int(tmpcount[0]) >= 2 and int(tmpcount[0]) < 74:
                    print "more than 1"
                    arcpy.management.SelectLayerByAttribute(fc, "NEW_SELECTION", SA_Filter)
                    arcpy.CalculateField_management(fc, "Angle", 
                                "!ANGLE!+90",
                                "PYTHON_9.3")
        except Exception as e:
            print "Error with message: {0}".format(e)

StuartMoore_0-1730371627898.png

 

0 Kudos
BrandonMcAlister
Frequent Contributor

@StuartMoore 

I understand your frustration I just wrote a piece of code that was going to take 60+ days....

It is weird that the OBJECTID exists but returns an invalid expression, it is almost like the fc variable is being rewritten to equal a different map layer and that why the expression fails

Thanks,
Brandon
HaydenWelch
MVP

Nesting Cursors is generally pretty bad, but it can be useful when you want the spatial query to be done in SQL instead of iterating the whole dataset for each feature in python:

 

import arcpy
from arcpy.da import SearchCursor, UpdateCursor, Editor
import os

def rotate_annotations(feature_class: os.PathLike, *, angle_field: str = 'Angle') -> None:
    field_names = ('OID@', 'SHAPE@', angle_field)
    
    with UpdateCursor(feature_class, field_names) as upd_cursor:
        for row in upd_cursor:
            oid, shape, angle = row
            intersecting_features = \
                [
                    feature
                    for feature in SearchCursor(feature_class, field_names, spatial_filter=shape)
                    if feature[0] != oid
                ]
            if intersecting_features:
                angle += 90.0
                upd_cursor.updateRow([oid, shape, angle])
    return

if __name__ == '__main__':
    
    fc = r"path\to\your\feature_class"
    wsp = arcpy.Describe(fc).workspace.catalogPath
    
    with Editor(wsp) as edit:
        try:
            rotate_annotations(fc)
        except Exception as e:
            print(e)
            edit.stopEditing(False)

 

I also threw the operation in an Editor session, which should prevent locks. Also since the rotation code is now a function call, you can call it multiple times on the data if you want to continue rotating annotations that entered a collision after the initial rotation was applied.