2

I have a fairly small script which is running a cursor on a small feature class (~2500 features) which is crashing python with a python.exe has stopped working message.

enter image description here

I have a cursor that loops over features, deletes any that don't meet a set criteria, looks up field value keys in a dictionary, and updates another field with the dictionary value. This works well. But if I add in a check to deleteRow() any records that have a Null or a value that doesn't start with the letter O.

arcpy.FeatureClassToFeatureClass_conversion(r"mydatabase.sde\mydatabase.dbo.SitePolygon", "in_memory", "xTempPolygon")

with arcpy.da.UpdateCursor(r'in_memory\xTempPolygon', ['RecID', 'LotID', 'Owner', 'Manager', 'Class']) as cursor:
    for row in cursor:
        if row[2] != 'CITY' or row[4][:4].upper() == 'ROAD' or row[3].upper() in ['WASTEWATER', 'STORMWATER', 'WATERSUPPLY']:
            cursor.deleteRow()
        elif row[0] in resultDict:
            row[1] = resultDict[row[0]]
            cursor.updateRow(row)

        #################################################
        # If I add this block, it crashes
        if row[1] is None or row[1][0].upper() != 'O':
            cursor.deleteRow()
        #################################################

The resultDict is a dictionary that comes from a SQL lookup that returns RecID and LotID. These are looked up in the cursor and populates the LotID on the feature based on its RecID.

If I leave out the final if block, it runs without issue. If I add it in it crashes. I need it there because I'm ending up with some records that have a NULL or a value that doesn't start with O in the LotID field. I need these records deleted.

I need the extra if to run after the update to allow for the update to run, as no records have any values in row[1] before the update - they are all NULL so they'd all be deleted.

What is causing this crash, and how do I avoid it?

5
  • 1
    You may be accessing the row after it has been deleted. If you have multiple flows that could delete, better to use a Boolean flag, then conditionally delete at the bottom of the loop. Print statements would help clarify what is happening.
    – Vince
    Commented Feb 21, 2017 at 20:11
  • What if you change the block to an elif and move it above the update block? Commented Feb 21, 2017 at 20:15
  • @NateWanner I can't - I need it to run after the update to allow for the update to run (as none of them have values in row[1] before the update
    – Midavalo
    Commented Feb 21, 2017 at 20:18
  • @Vince you may be onto something. I hadn't considered the fact that I was trying to access the row after it was deleted
    – Midavalo
    Commented Feb 21, 2017 at 20:18
  • @Vince If you would post that as an answer I'll accept it, as you pointed me right at the problem
    – Midavalo
    Commented Feb 21, 2017 at 20:34

1 Answer 1

3

Thanks to @Vince and @NateWanner for two suggestions that pointed me in the right direction.

As @Vince had commented, I was trying to access a row that had been deleted.

I created an else block and moved my elif (and turned it into if) and the failing if block into the else so that it would only process on rows that hadn't yet been deleted.

arcpy.FeatureClassToFeatureClass_conversion(r"mydatabase.sde\mydatabase.dbo.SitePolygon", "in_memory", "xTempPolygon")

with arcpy.da.UpdateCursor(r'in_memory\xTempPolygon', ['RecID', 'LotID', 'Owner', 'Manager', 'Class']) as cursor:
    for row in cursor:
        if row[2] != 'CITY' or row[4][:4].upper() == 'ROAD' or row[3].upper() in ['WASTEWATER', 'STORMWATER', 'WATERSUPPLY']:
            cursor.deleteRow()
        else:
            if row[0] in resultDict:
                row[1] = resultDict[row[0]]
                cursor.updateRow(row)
            if row[1] is None or row[1][0].upper() != 'O':
                cursor.deleteRow()

This is now working as desired, although thinking on the two comments further leads me to believe there may be even better ways to construct this cursor that'll I'll investigate.

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.