Thursday 30 November 2017

arcpy - Using LIKE clause in update cursor gives syntax error?


I am trying to write a second update cursor within one script. This requires a LIKE condition to look up a value within the same layer to identify rows to update the field within that layer (first update cursor looks up a second table and is working successfully). When I try to run the query it is throwing a syntax error and highlighting LIKE.


See my initial question about Writing python script to select attributes not in growing table with over 4000 values?.



Here is the portion of script in causing the issue:


with arcpy.da.UpdateCursor("in_memory/headphotos",[field2,'Located']) as UCur1:
for URow1 in UCur1:
if URow1[0].lower() LIKE '%reserve%':
URow1[1] = 1

Here is my full script:


import os, sys, arcpy

arcpy.env.workspace = (directory location)

jpgList = arcpy.ListRasters('*','JPG')
photos = ([s.lower().strip('.jpg') for s in jpgList ])

arcpy.CopyFeatures_management(feature class location,r"in_memory/headphotos")

arcpy.AddField_management(r"in_memory/headphotos",'Located','SHORT')

with arcpy.da.UpdateCursor("in_memory/headphotos",['ce_id','Located']) as UCur:
for URow in UCur:
if URow[0].lower() in photos:

URow[1] = 1
else:
URow[1] = 0
UCur.updateRow(URow)

with arcpy.da.UpdateCursor("in_memory/headphotos",[field2,'Located']) as UCur1:
for URow1 in UCur1:
if URow1[0].lower() LIKE '%reserve%':
URow1[1] = 1


arcpy.MakeFeatureLayer_management("in_memory/headphotos","tmp_layer",'Located = 0')
arcpy.CopyFeatures_management("tmp_layer",new layer)

Answer



Expanding on the comment.


There's two ways set your rows that contain 'reserve' location attribute to 1, but first I must point out your 2nd update cursor does not contain UCur1.updateRow(URow1) so no matter what no rows are updated.


Firstly by where clause:


with arcpy.da.UpdateCursor("in_memory/headphotos",[field2,'Located'],'{} like \'%reserve%\''.format(field2)) as UCur1:
for URow1 in UCur1:
URow1[1] = 1 # all rows contain the word 'reserve' in their field2.
UCur1.updateRow(URow1) # store the updated row


Where can this be a problem? The wildcard character is different for different feature class types.. % is fine most of the time but personal geodatabases use * as a wildcard which can cause horrible problems when reusing code.


Secondly by finding a substring:


with arcpy.da.UpdateCursor("in_memory/headphotos",[field2,'Located']) as UCur1:
for URow1 in UCur1:
if URow1[0].lower().find('reserve') > 0:
URow1[1] = 1 # this row is found to contain 'reserve'
UCur1.updateRow(URow1) # store the updated row

So what's the problem with doing it this way? You're still going through all the rows again, this mightn't be a big deal in small datasets but it can be more significant in very large datasets where the power of some SQL to limit the number of rows that python has to chug through gives a significant advantage; SQL is usually faster than python.



On a side note, I see you've made the 2nd cursor UCur1 to avoid reusing the name, this often is commendable, however by the time the execution gets to the second update cursor UCur and URow from the first cursor are out of scope and therefore do not exist - as far as python is concerned it's already forgotten them! Don't feel that you need to have a different variable name for every cursor... I've used the name UCur/URow to remind me that it's an update environment (read/write), were it a search cursor I might use SCur/SRow to remind me it's a search environment (read only) but as soon as you finish the with block those names are safe to be reused.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...