Best way to add values to a string for UpdateCursor

703
13
Jump to solution
07-06-2021 03:43 PM
JamesWilcox1970
New Contributor III

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.

 

0 Kudos
1 Solution

Accepted Solutions
JamesWilcox1970
New Contributor III

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!

View solution in original post

0 Kudos
13 Replies
DanPatterson
MVP Esteemed Contributor

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?


... sort of retired...
0 Kudos
JamesWilcox1970
New Contributor III

Lines 10-14 are supposed to build the output string for the UpdateCursor...once it gets there. But it doesn't get there. 

0 Kudos
DanPatterson
MVP Esteemed Contributor

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 '

... sort of retired...
0 Kudos
BlakeTerhune
MVP Regular Contributor

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))
JeffK
by MVP Regular Contributor
MVP Regular Contributor

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.

0 Kudos
BlakeTerhune
MVP Regular Contributor

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.

0 Kudos
JeffK
by MVP Regular Contributor
MVP Regular Contributor
Ah yes I forgot it does. Thanks!
0 Kudos
JamesWilcox1970
New Contributor III

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!

0 Kudos
BlakeTerhune
MVP Regular Contributor

@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.

0 Kudos