I am still really new to Python and ArcPy. We have a pair of feature classes, one with an index grid and the other with project locations. We are trying to create a table that shows what index grid cells each project intersects.
I have a script that performs Intersect on the two feature classes, creates a new table (indexTable) , adds the two needed fields: Label (the project number) and PageName (the index grid), and populates Label using an InsertCursor. I know that I eventually need to use an UpdateCursor with an update string to update PageName, but I am at a loss on how to properly do it, since some of the projects intersect more than one grid cell.
Currently, I have a SearchCursor to get the data from the Intersect feature class, but it breaks with "SystemError: error return without exception set".
# UpdateCursor to add all index grid cells for each label
gridList = [r for r in arcpy.da.SearchCursor(intersectOut, ("Label", "PageName"))] # List from intersection
arcpy.AddMessage("Grid list = {}".format(gridList)) # For debugging
with arcpy.da.UpdateCursor(indexTable, ("Label", "PageName")) as uCursor:
for row in uCursor:
name_field = "Label"
expression = u'{} = {}'.format(arcpy.AddFieldDelimiters(intersectOut, name_field), row[0])
# expression = "Label = '" + row[0] + "'"
with arcpy.da.SearchCursor(intersectOut, ("Label", "PageName"), where_clause=expression) as sCursor:
gridString = ""
if gridString == "":
gridString = gridString + sCursor[1]
else:
gridString = gridString + ", " + sCursor[1]
arcpy.AddMessage(gridString)
# Before going to the next record in the site index table write this list to the appropriate field.
row[1] = gridString
uCursor.updateRow(row)
I also tried using list comprehension to go through gridList, based on row[0] of the UpdateCursor, but that just returns a series of empty lists--and I was unsure where to go from there in any case.
# UpdateCursor to add all index grid cells for each label
gridList = [r for r in arcpy.da.SearchCursor(intersectOut, ("Label", "PageName"))] # List from intersection
arcpy.AddMessage("Grid list = {}".format(gridList)) # For debugging
with arcpy.da.UpdateCursor(indexTable, ("Label", "PageName")) as uCursor:
for row in uCursor:
search = row[0]
arcpy.AddMessage(search)
filterList = [r for r in gridList if gridList[0] == search]
I know there has to be a way to do this, but I am at a loss.
Solved! Go to Solution.
Thank you @BlakeTerhune ! It is going to take me a little bit to understand it, try it out and hammer out any bugs, but I have very high hopes now. I will update you as I go. Thanks again!
what is line 10 and 11 doing? you never get to 13 and 14
sample messages? or does it fail before it even gets to an addmessage?
Lines 10-14 are supposed to build the output string for the UpdateCursor...once it gets there. But it doesn't get there.
throw in some print statements since addmessage doesn't report anything?
In any event, if you are trying to figure out how to concatenate values from fixed length and potentially variable length inputs, throw them both into a list, add the lists and format accordingly
a0 = ["fixed length"]
a1 = [1, 2, 3]
("{} "*len(a0+a1)).format(*(a0+a1))
'fixed length 1 2 3 '
Here's a blog you should read. It's got some techniques for doing stuff like this that I have found very useful.
Turbo Charging Data Manipulation with Python Curso... - Esri Community
Basically you'll read your "look up" data into a dictionary and reference it by some id to get the value you want to write elsewhere. If I'm understanding your logic correctly, it would look something like this.
# UpdateCursor to add all index grid cells for each label
gridList = {label: pageName for label, pageName in arcpy.da.SearchCursor(intersectOut, ("Label", "PageName"))} # List from intersection
arcpy.AddMessage("Grid list = {}".format(gridList)) # For debugging
with arcpy.da.UpdateCursor(indexTable, ("Label", "PageName")) as uCursor:
for label, pageName in uCursor:
gridList_pageName = gridList.get(label)
arcpy.AddMessage(gridList_pageName)
# Before going to the next record in the site index table
# write the PageName from gridList if there is one.
if gridList_pageName:
uCursor.updateRow((label, gridList_pageName))
else:
arcpy.AddWarning("Label {} not found in gridList; nothing updated.".format(label))
You might get a Key Error in 6 if the label is not in the gridList.
gridList_pageName = gridList.get(label, None)
Will default the gridList_pageName to None if the key is not found and will continue execution.
I like dict.get() because it returns None by default if the key is not found. You can specify a different value in the second argument but None is redundant.
Thanks for looking at it! This works great, if there were only one index grid that each project falls in. Unfortunately, using a dictionary limits me to just one index grid for each project. The issue I am having is that there are several projects that fall into multiple grids.
I will keep plugging away at it.
Thanks again!
@JamesWilcox1970, this is a new requirement from your initial post. Please describe all the rules in which these projects are grouped into index grids and we can help you find a solution.