What's the best approach for updating the geometry of a point feature using the point geometry of a feature from a different feature class? I've been trying to use an Update Cursor to do this.

553
4
11-19-2018 09:21 AM
AngelaDeegan
Occasional Contributor

What's the best approach for updating the geometry of a point features (which start out as null) using the point geometry of a feature from a different feature class? I've been trying to use an Update Cursor to do this. I know how to get it to update a regular attribute, but not a geometry. And in my testing, it's looking like this may not be workable. I keep getting "TypeError: 'tuple' object does not support item assignment" which I find odd because when I check the type, it's "float".

Update: Okay, based on what Adrian pointed out, I changed the iterator in the inner, Search Cursor loop to "row2" and it now works fine. Silly me, I had been thinking "row" was a reserved word:) 

I've pasted my new code below. Thank you all - and I'll try to always post correctly formatted code in the future.  

import arcpy, datetime

arcpy.env.workspace = r'Database Connections\dev-sde.sde'  # type: str
ws = arcpy.env.workspace
# Start an edit session
edit = arcpy.da.Editor(ws)

edit.startEditing(False, True) # Change second parameter to True for versioned data
edit.startOperation()

fcs = (r"dev.sde.wControlValve",r"dev.sde.wSystemValve",r"dev.sde.wFitting")
dt = datetime.datetime.strptime("01/01/1970", "%d/%m/%Y")
fd = r"dev.sde.WaterDistribution"  # type: str

outer_cnt= 0
inner_cnt = 0
cnt_not_found = 0
with arcpy.da.UpdateCursor("{0}\{1}".format(fd,r"dev.sde.wPump"),[r"project",r"SHAPE@XY"]) as ucursor:
    for row in ucursor:
        print(row[0], row[1])
        print(type(row[0]))
        print(type(row[1]))
        src_prj = row[0]
        found = "false"
        print(src_prj)
        x = 0.0
        y = 0.0
        for fc in fcs: #Start searching through features in the point feature classes for feature with same project #
            print(fc)
            with arcpy.da.SearchCursor(("{0}\{1}".format(fd, fc)), [r"project", r"SHAPE@XY"]) as icursor:
                for row2 in icursor:
                    if row2[0]==src_prj:
                        #new_geom = row[1]
                        (x,y) = row2[1]
                        #print(type(new_geom))
                        #print(new_geom)
                        found = "true"
                        break
            if found == "true":
                print(found)
                break #Don't need to search in any further feature classes
        if found == "true":
            print(type(row[1]))
            row[1] = (x,y)
            ucursor.updateRow(row)
        else:
            cnt_not_found+=1

# Stop Edit Session
edit.stopOperation()
edit.stopEditing(True)
print(str(cnt_not_found)+ " project #s were not found in the listed feature classes")

del icursor
del ucursor

0 Kudos
4 Replies
DanPatterson_Retired
MVP Emeritus

Angela... although there have been issues with code formatting recently... give this a try

/blogs/dan_patterson/2016/08/14/script-formatting 

since you formatting is hard to follow and lacks line numbers.

Also.. lots of print statements, can you share some since the details may lie there.

0 Kudos
AdrianWelsh
MVP Honored Contributor

Angela,

Can you format your code using the syntax highlighter on GeoNet? It will make it easier to read and parse through:

/blogs/dan_patterson/2016/08/14/script-formatting 

EDIT: Whoops, Dan beat me to it!

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

All of your indentation is lost, it would be helpful to use the Syntax highlighter or some other way to post your code with proper indentation.

Looking at your comment about the error itself:

"TypeError: 'tuple' object does not support item assignment" which I find odd because when I check the type, it's "float".

Python tuples are immutable, which means they cannot be updated or modified once they are created.  Looking over your code, you are using row for both your update and search cursors, and your search cursor is nested within your update cursor.  In short, you are overriding your row assignment from the update cursor with the row assignment from the search cursor.  By the time you get to the line:

row[1] = x

The row variable contains a tuple, not a list, so you receive the error.

JoeBorgione
MVP Emeritus

I copied the code from above into Spyder, and pasted it into a syntax highlighter window; I hope I got the indents correct.  Personally, I try to avoid nesting cursors within cursors.  They tend to get ugly as you are experiencing. 

As Joshua points out, your duplicate use or 'row' is problematic. If you are going to nest your cursors, I suggest associating the rows with the cursor like ucursor/urow, icursor/irow. 

Also, why the 'breaks' at lines 45 & 50: again, just personal preference, I'd go with else: pass as shown below:

arcpy.env.workspace = r'Database Connections\dev-sde.sde' # type: str
ws = arcpy.env.workspace
# Start an edit session
edit = arcpy.da.Editor(ws)

 

edit.startEditing(False, True) # Change second parameter to True for versioned data
edit.startOperation()

 

fcs = (r"dev.sde.wControlValve",r"dev.sde.wSystemValve",r"dev.sde.wFitting")
dt = datetime.datetime.strptime("01/01/1970", "%d/%m/%Y")
fd = r"dev.sde.WaterDistribution" # type: str

outer_cnt= 0
inner_cnt = 0
with arcpy.da.UpdateCursor("{0}\{1}".format(fd,r"dev.sde.wPump"),[r"project",r"SHAPE@X", "SHAPE@Y"]) as ucursor:
    for row in ucursor:
        #geom = row[1] #old geom
        #new_geom = geom
        new_geom = "" # type: str
        print(row[0], row[1], row[2])
        print(type(row[0]))
        print(type(row[1]))
        src_prj = row[0]
        found = "false"
        print(found =="true")
        print(src_prj)
        x = 0.0
        y = 0.0
        for fc in fcs: #Start searching through features in the point feature classes for feature with same project #
            print(fc)
            with arcpy.da.SearchCursor(("{0}\{1}".format(fd, fc)), [r"project", r"SHAPE@X", r"SHAPE@Y"]) as icursor:
                for row in icursor:
                    if row[0]==src_prj:
                        #new_geom = row[1]
                        x = row[1]
                        y = row[2]
                        #print(type(new_geom))
                        print (type(x))
                        #print(new_geom)
                        found = "true"
                        break
                        # else:
                        #   pass
                    if found == "true":
                        print(found)
                        break #Don't need to search in any further feature classes
                    # else:
                    #   pass
                    if found == "true":
                        print(type(row[1]))
                        print(type(row[2]))
                        print(type(x))
                        row[1] = x
                        row[2] = y
                        ucursor.updateRow(row)

 


    # Stop Edit Session
    # Stop Edit Session
    edit.stopOperation()
    edit.stopEditing(True)

 

del icursor
del ucursor
That should just about do it....