2

I'm using an update cursor to iterate through my feature class, create a selection and then delete the row if it meets the condition. It partially works - I get no error messages and the script completes but then a couple of seconds later ArcGIS crashes and the resulting feature class does not have all the selected features removed. I presume I must be using the update cursor incorrectly. Here is my code:

newcur = arcpy.UpdateCursor("outlayer")
for row in newcur:
    if row.LAND1 =="Single Family ( Attached/Detached )" and row.LAND2 =="Single Family ( Attached/Detached )":
        newcur.deleteRow(row)
        newcur.updateRow(row)
    if row.LAND1 =="Multi Family Residential" and row.LAND2 =="Multi Family Residential":
        newcur.deleteRow(row)
        newcur.updateRow(row)
    if row.LAND1  =="Multi Family Residential" and row.LAND2 =="Single Family ( Attached/Detached )":
        newcur.deleteRow(row)
        newcur.updateRow(row)
    if row.LAND1 =="Single Family ( Attached/Detached )" and row.LAND2 =="Multi Family Residential":
        newcur.deleteRow(row)
        newcur.updateRow(row)
    if row.LAND1 =="Public Institutions: Schools" and row.LAND2 =="Public Institutions: Schools":
        newcur.deleteRow(row)
        newcur.updateRow(row)
    if row.LAND1 =="University Semi Govt" and row.LAND2 =="University Semi Govt":
        newcur.deleteRow(row)
        newcur.updateRow(row)
    if row.LAND1=="Park / Recreation / Open Space" and row.LAND2 =="Park / Recreation / Open Space":
        newcur.deleteRow(row)
        newcur.updateRow(row)
del newcur,row
gc.collect()
  • Why first delete and then update the row? Ommit the second statement. – HimBromBeere Jan 19 '16 at 9:23
  • schoolboy error ... – wunderkind Jan 19 '16 at 11:30
1

I would tackle this problem a little differently. Cursors are great, but you really don't need one here. You basically want to select records according to a giant SQL Query, and delete those records.

First, build up your query bit by bit, to make it more manageable. I would test the selections first individually and as a group:

a = """"LAND1" = 'Single Family ( Attached/Detached )'""" and """"LAND2" = 'Single Family ( Attached/Detached )'"""
b = """"LAND1" = 'Multi Family Residential'""" and """"LAND2" = 'Multi Family Residential'"""
c = """"LAND1" = 'Multi Family Residential'""" and """"LAND2" = 'Single Family ( Attached/Detached )'"""
d = """"LAND1" = 'Single Family ( Attached/Detached )'""" and """"LAND2" = 'Multi Family Residential'"""
e = """"LAND1" = 'Public Institutions: Schools'""" and """"LAND2" = 'Public Institutions: Schools'"""
f = """"LAND1" = 'University Semi Govt'""" and """"LAND2" = 'University Semi Govt'"""
g = """"LAND1" = 'Park / Recreation / Open Space'""" and """"LAND2" = 'Park / Recreation / Open Space'"""

SQLExpression = a + 'OR' + b + 'OR' + c + 'OR' + d + 'OR' + e + 'OR' + f + 'OR' + g 

arcpy.SelectLayerByAttribute_management("outLayer", "NEW_SELECTION", SQLExpression)

Once the appropriate rows are selected, you can delete:

arcpy.DeleteRows_management("outLayer")

Also, I'm generally not a huge fan of deleting data. You might consider writing a definition query, or select the things you don't want in the table, switch the selection, and export the rest to a new feature class.

  • Thanks for your suggestion - I tried your suggestion on 21000 records and got <class 'arcgisscripting.ExecuteError'>: ERROR 000426: Out Of Memory Failed to execute (SelectLayerByLocation) - I have 64bit OS and 24GB - looking into why this would crash in model builder and will get back to you. – wunderkind Feb 16 '16 at 14:47
  • Additionally I have tried it in the Python window without sucess: >>> a = '"LAND1" = Single Family ( Attached/Detached ) and "LAND2" = Single Family ( Attached/Detached )' >>> SQLExpression = a >>> arcpy.SelectLayerByAttribute_management("outlayer","NEW_SELECTION",SQLExpression) Runtime error <class 'arcgisscripting.ExecuteError'>: ERROR 000358: Invalid expression Failed to execute (SelectLayerByAttribute). – wunderkind Feb 16 '16 at 15:20
  • The SQLExpression containing backslashes created for 'g' does not work. Considering how I can pass this using some other means – wunderkind Feb 17 '16 at 10:52
  • For your first question here, you should be selecting by attribute, not location. For question #2, double check that your strings are exactly as they appear in your data, including spaces. For questions #2 & #3, python might be interpreting your backslashes as escapes. Try making the SQL statements into raw strings (e.g. r'string stuff'). See the discussion here: stackoverflow.com/q/301068/5641121 – Priscilla Feb 19 '16 at 16:32
  • Apologies, question #1 occurred due to an error in a different part (unrelated) of the script. For #2&#3 - I have no control over the attribute values and it seems that the multiple backslashes are causing the problem. I have tried to create a code object for the following selection: "LAND1"= 'Park / Recreation / Open Space' AND "LAND2"= 'Park / Recreation / Open Space' I have tried various incarnations of : code_string = """"LAND1"= 'Park / Recreation / Open Space'""" code_obj = compile(code_string,'<string>', 'exec') This gives an error. Can I use code objects in this way? – wunderkind Feb 28 '16 at 14:34
1

First you don't need to use updateRow() when you delete a row.

Also, all your conditions are exclusive, so using elif instead of if would be neater and probably speed up your code a little bit.

And third, calling the garbage collector gc.collect() is pretty useless here, just remove it.

So your code would look like this:

newcur = arcpy.UpdateCursor("outlayer")
for row in newcur:
    if row.LAND1 =="Single Family ( Attached/Detached )" and row.LAND2 =="Single Family ( Attached/Detached )":
        newcur.deleteRow(row)
    elif row.LAND1 =="Multi Family Residential" and row.LAND2 =="Multi Family Residential":
        newcur.deleteRow(row)
    elif row.LAND1  =="Multi Family Residential" and row.LAND2 =="Single Family ( Attached/Detached )":
        newcur.deleteRow(row)
    elif row.LAND1 =="Single Family ( Attached/Detached )" and row.LAND2 =="Multi Family Residential":
        newcur.deleteRow(row)
    elif row.LAND1 =="Public Institutions: Schools" and row.LAND2 =="Public Institutions: Schools":
        newcur.deleteRow(row)
    elif row.LAND1 =="University Semi Govt" and row.LAND2 =="University Semi Govt":
        newcur.deleteRow(row)
    elif row.LAND1=="Park / Recreation / Open Space" and row.LAND2 =="Park / Recreation / Open Space":
        newcur.deleteRow(row)
del newcur,row
  • Unfortunately this still does not work.....executing it in the Python window actually reports a syntax error with the if statements. This hadn't happened with the script running in model builder which as I mentioned completed without errors. – wunderkind Jan 19 '16 at 11:13
  • I have tried using SelectLayerByAttribute_management within the update cursor loop utilizing a predefined where clause for each condition but run into similar problems. – wunderkind Jan 19 '16 at 11:27
  • What is your syntax error? Where do you actually run your script, in ArcMap/ArcCatalog/other IDE? From the Python window, ModelBuilder, or script tool? What is "outlayer", a feature class on your disc or a layer in the TOC? – GISGe Jan 19 '16 at 12:06
  • It is running as script in Modelbuilder in ArcMap. The script creates an on my disk just prior to this step and then I used make feature layer to create 'outlayer'. I just tried the select by attribute option in the python window. – wunderkind Jan 19 '16 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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