3

I am new to ArcPy and I am trying to write a code to select specific rows from a shapefile. I wrote this code, which gives back:

Parsing error SyntaxError: invalid syntax (line 3)

Any suggestions about how to fix it?

    import arcpy
    arcpy.env.workspace = 'C:/data'
    arcpy.env.overwriteOutput = True
    fc = 'hospital.shp'
    with arcpy.da.UpdateCursor(fc, "Layer") as rows
        for row in rows:
            if row = "02-R00-04-B$0$210"
                pass
            elif row = "02-R16-04-B$0$210"
                pass
            elif row = "02-R00-04-B$0$220"
                pass
            elif row = "02-R16-04-B$0$220"
                pass
            elif row = "02-R00-04-B$0$211"
                pass
            elif row = "02-R16-04-B$0$211"
                pass
            elif row = "02-R00-04-B$0$320"
                pass
            elif row = "02-R16-04-B$0$320"
                pass
            else:
                rows.deleteRow()
    del rows
    del row
2

@Simon.y's answer is solid, and I like that it uses the setup you already had (only with the problems corrected). Having upvoted that, another way to perform this with fewer lines and better memory efficiency is to use a where clause in your UpdateCursor call, like this:

import arcpy
arcpy.env.workspace = "C:\\data" 
arcpy.env.overwriteOutput = True
fc = "hospital.shp"
query = "NOT Layer IN ('02-R00-04-B$0$210','02-R16-04-B$0$210','02-R00-04-B$0$220','02-R16-04-B$0$220','02-R00-04-B$0$211','02-R16-04-B$0$211','02-R00-04-B$0$320','02-R16-04-B$0$320')"
with arcpy.da.UpdateCursor(fc, "Layer", where_clause=query) as rows:
    for row in rows:
        rows.deleteRow()
1

Here is your code with proper syntax. That error is saying that line 3 (arcpy.env.overwriteOutput = True) has invalid syntax. This line has correct syntax, however when I copied your code over to my IDE it copied with an indent, this could be the problem. Otherwise I am not sure about that error (Is this your entire script?). That being said I don't think you would even need to set the overwrite environment variable for this script. Update cursor does not create a new output it modifies an existing table.

You have to be very careful about indents and ':' in python, it is sensitive to these and will produce errors or prevent your script from functioning properly.

Additionally = and == are different. '=' is and assignment of a value and '==' is a comparison of two values. See here.

import arcpy
arcpy.env.workspace = "C:\\data" 
arcpy.env.overwriteOutput = True
fc = "hospital.shp"
with arcpy.da.UpdateCursor(fc, "Layer") as rows:
    for row in rows:
        if row == "02-R00-04-B$0$210":  
            pass
        elif row == "02-R16-04-B$0$210":
            pass
        elif row == "02-R00-04-B$0$220":
            pass
        elif row == "02-R16-04-B$0$220":
            pass
        elif row == "02-R00-04-B$0$211":
            pass
        elif row == "02-R16-04-B$0$211":
            pass
        elif row == "02-R00-04-B$0$320":
            pass
        elif row == "02-R16-04-B$0$320":
            pass
        else:
            rows.deleteRow()
    del rows
    del row
  • 1
    This corrects the issue. One note - the del rows and del row at the end are unnecessary, as these objects are wiped when the "with" clause completes. – AlecZ May 9 '18 at 18:43
  • A data access cursor returns an iterater of tuples. Thus, row will never equal a string. It will always be a tuple. – Emil Brundage May 10 '18 at 0:24
  • Neat, new info to me. If it is a tuple, what is the proper syntax to test equivalency? Or, is the where clause the best way to go? – Simon.y May 10 '18 at 17:03
  • @Simon.y the correct syntax would be a one-item tuple, so something like elif row == ("02-R16-04-B$0$320",): – Emil Brundage May 10 '18 at 21:01
  • @Simon.y You can also unpack the tuple in your for loop. Example: for row, in rows: if row == "02-R00-04-B$0$210":.... Note the comma after row in the for loop. – Emil Brundage May 10 '18 at 21:20
1

applying an SQL query to your cursor as described by @AlecZ is a good option. If you prefer a slower but easier-to-read option you can put all your keep values in a list. Iterate through your rows and check that the field value is in the list. If not, delete the row.

import arcpy
arcpy.env.workspace = 'C:/data'
arcpy.env.overwriteOutput = True
fc = 'hospital.shp'

keepVals = ["02-R00-04-B$0$210",
            "02-R00-04-B$0$220",
            "02-R16-04-B$0$210",
            "02-R00-04-B$0$220",
            "02-R16-04-B$0$220",
            "02-R00-04-B$0$211",
            "02-R16-04-B$0$211",
            "02-R00-04-B$0$320",
            "02-R16-04-B$0$320"]

with arcpy.da.UpdateCursor(fc, "Layer") as rows:
    for val, in rows:
        if not val in keepVals:
            rows.deleteRow()

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.