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.MakePeaceGreatAgain– MakePeaceGreatAgain2016年01月19日 09:23:55 +00:00Commented Jan 19, 2016 at 9:23
-
schoolboy error ...wunderkind– wunderkind2016年01月19日 11:30:27 +00:00Commented Jan 19, 2016 at 11:30
2 Answers 2
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– wunderkind2016年02月16日 14:47:14 +00:00Commented Feb 16, 2016 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– wunderkind2016年02月16日 15:20:42 +00:00Commented Feb 16, 2016 at 15:20
-
The SQLExpression containing backslashes created for 'g' does not work. Considering how I can pass this using some other meanswunderkind– wunderkind2016年02月17日 10:52:20 +00:00Commented Feb 17, 2016 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/5641121Priscilla– Priscilla2016年02月19日 16:32:03 +00:00Commented Feb 19, 2016 at 16:32
-
Apologies, question #1 occurred due to an error in a different part (unrelated) of the script. For #2 - 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– wunderkind2016年02月28日 14:34:07 +00:00Commented Feb 28, 2016 at 14:34
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– wunderkind2016年01月19日 11:13:51 +00:00Commented Jan 19, 2016 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– wunderkind2016年01月19日 11:27:56 +00:00Commented Jan 19, 2016 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– GISGe2016年01月19日 12:06:54 +00:00Commented Jan 19, 2016 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– wunderkind2016年01月19日 14:56:47 +00:00Commented Jan 19, 2016 at 14:56