Problem committing edits with arcpy.da.updatecursor

5527
6
01-22-2014 09:57 AM
JamesGraham
New Contributor III
I'm having a whale of a time trying to use the arcpy.da.updatecursor while using an edit session to update the feature data.  Here's the problem:

I've got a script that is trying to update an unversioned point feature class in ArcSDE.  The user role has edit privileges to this specific FC.  I'll include the relevant bits of my code, but if you'd like to see the whole enchilada let me know and thanks in advance for your help.

Here, I'm querying webservice (inside the 'getNearestAddress' function) then building a dictionary with the result.  This works without error:
    with arcpy.da.SearchCursor(points, ('NEARBYADDRESS', 'BLOCK','STREET','SHAPE@X', 'SHAPE@Y', 'OID@')) as cursor:
        for row in cursor:
        
            #if row[5] < 100:
            thisoid = str(row[5])
            point_info = getNearestAddress(row[3], row[4])
            #returns a list like this ['Street Address','Block Description','Street Name'] or if no address found ['No Address Nearby']
            
            if str(point_info) == "No Address Nearby":
                myinfo[thisoid] = {"address" : "No Address Nearby"} 
                myinfo[thisoid]["block"] = "Unknown"
                myinfo[thisoid]["street"] = "Unknown"

            else:                     
                myinfo[thisoid] = {"address" : "".join(point_info[0])} #first value in the dictionary looks like this... create a key
                myinfo[thisoid]["block"] = "".join(point_info[1])
                myinfo[thisoid]["street"] = "".join(point_info[2])
                #the resulting dictionary of a couple of entries will look like this:
                #{123: {'address': "123 Main Street", 'block': "100 Block of Main Street", 'street': "Main Street"},
                #456: {'address': "456 South Street", 'block': "400 Block of South Street", 'street': "South Street"}}


Next, I try to populate the fields of the same FC using the info stored in the dictionary.  When the script gets to edit.stopOperation(), I get the error: error return without exception set:

    edit = arcpy.da.Editor(workspace)

    # Edit session is started without an undo/redo stack for versioned data
    #  (for second argument, use False for unversioned data)
    edit.startEditing(False, False)

    # Start an edit operation
    edit.startOperation()

    # Insert a row into the table.
    with arcpy.da.UpdateCursor(points, ('NEARBYADDRESS','BLOCK','STREET','OID@')) as cursor:
        for row in cursor:
                
            print "Currently on... " + str(row[3])
            if row[3] < 100:

                ##This will successfully save to the feature class!
                row[0] = "123 Dummy Address"
                row[1] = "100 Block of Dummy"
                row[2] = "Dummy"

                ##This will NOT save to the feature class!!
                row[0] = myinfo[str(row[3])]["address"]
                row[1] = myinfo[str(row[3])]["block"]
                row[2] = myinfo[str(row[3])]["street"]
                
                cursor.updateRow(row)
                totalpointsupdated +=1
                
    # Stop the edit operation.  THIS IS WHERE THE ERROR OCCURS
    edit.stopOperation()

    # Stop the edit session and save the changes
    edit.stopEditing(True)
Tags (2)
0 Kudos
6 Replies
T__WayneWhitley
Frequent Contributor
Your code looks sound except you forgot your populated 'myinfo' dictionary OID keys are integers...your 'lookup' update cursor code is attempting to use string keys.  That creates an exception which isn't really handled - I won't go into that, but you have enough to know how to modify your code.

BTW, I may not know what the whole enchilada is on your OID handling -maybe you've got that adequately covered- but don't know how advisable it is to use the OID from one table to use in updating another table?

So, bottom line, your code should at least run with "myinfo[row[3]]['...']" statements.


Wayne
0 Kudos
PeterLee1
New Contributor
James hi,

I believe your problem may not be solved just by changing myinfo[str(row[3])]["address"] to myinfo[row[3]]["address"].

Actually, I currently get stuck with the same issue with my code (below). I have printout saying "row[0] update OK" for all records but with the same error 'error return with exception set' at the line edit.stopOperation().

It would be great to learn if you got this issue resolved and if so, how?

Cheers.
Peter Lee
ePlanning Data Specialist, NSW Dept of Planning

edit = arcpy.da.Editor(workspace)
edit.startEditing(False, True)
edit.startOperation()
rows = arcpy.da.UpdateCursor(fc, fieldnames, delimitedfield_1 + " = '" + epi_name + "'")
for row in rows:
            row[2] = '2013-418'
            row[3] = 'http://www.legislation.nsw.gov.au/maintop/scanact/inforce/EPITITLE/B/0'
            row[4] = 'http://www.legislation.nsw.gov.au/maintop/view/inforce/epi+418+2013+cd+0+N'
            row[5] = 'http://www.legislation.nsw.gov.au/mapindex?type=epi&year=2013&no=418'
            rows.updateRow(row)                                   
            print str(row[0]) + ' update OK '
edit.stopOperation()
edit.stopEditing(True)
0 Kudos
RichardHughes3
New Contributor III
                          try:
                                        ID_check = entry[0]
                                        print entry[0]
                                        intable = "in_memory\ID_Check"
                                        counter = 0
                                        with da.SearchCursor(intable,["ID"]) as cursor:
                                            for row in cursor:
                                                if row[0] == ID_check:
                                                    counter += 1
                                                   
                                        if counter >= 1:
                                            pythonaddins.MessageBox("This Feature's ID is a duplicate.  Solve thi                                                                                s error before continuing!","Error",0)
                                            raise Exception()
                                       
                                        elif counter == 0:
                                            print "All is good, this ID is not a duplicate."
                                            cursor = arcpy.da.InsertCursor(intable,["ID"])
                                            cursor.insertRow([ID_check])
                                            del cursor

                                            edit = da.Editor(workspace)
                                            edit.startEditing(False,True)
                                            edit.startOperation()
                                           
                                            with da.UpdateCursor(targetlayer,fields) as cursor:
                                                for row in cursor:
                                                    row = entry
                                                    print "row: {}".format(row)
                                                    cursor.updateRow(row)
                                                   
                                            del cursor
                                            del row
                                            edit.stopOperation()
                                            #edit.stopEditing(True)
                                           
                                           
                                    except Exception as e:
                                        print e.message
                                        print arcpy.GetMessages()
                                       
                                    arcpy.RefreshActiveView()
                                    print "Complete"
                               


When using "print edit.isEditing" after each edit method they are all true.  When I uncomment the line edit.stopEditing(True) an exception is thrown before the print statement saying Start Edit Session.  This happens in a versioned sde environment.  When using the same code in a personal geodatabase the exception message states something like "unable to perform within an edit session."

So my solution for sde is to comment out the stop editing method.  This works however if I create a feature then save edits.  If I later change the attributes or geometry of that feature the state of the geodatabase changes and the edits cannot be saved.  "Attempting to perform action on a closed state.  Unable to save edits."
0 Kudos
JamesGraham
New Contributor III
Hi Wayne, thanks for your comment.

Actually when populating the key in the first code block (4th or 5th) line, I am converting the OID to string when storing the key value.  If I didn't have the key (as text), then I would be getting some sort of python key error because it wouldn't exist in the dict.  It's finding it, but something else is going on, I believe.

Your code looks sound except you forgot your populated 'myinfo' dictionary OID keys are integers...your 'lookup' update cursor code is attempting to use string keys.  That creates an exception which isn't really handled - I won't go into that, but you have enough to know how to modify your code.

BTW, I may not know what the whole enchilada is on your OID handling -maybe you've got that adequately covered- but don't know how advisable it is to use the OID from one table to use in updating another table?

So, bottom line, your code should at least run with "myinfo[row[3]]['...']" statements.


Wayne
0 Kudos
JamesGraham
New Contributor III
Peter, I have yet to find a workaround, but Richard's suggestion seems promising.  I hacked an ugly workaround (even more ugly than what's above :D), but will give Richard's suggestion a try to see if this works.

Seems to me that the info stored in my dict() is just fine.  I can enter a set of keys, and return the data just fine if I'm at a break.  I'm a little baffled as to why it won't store on the row even though the data seems perfectly legit.  :confused:

Thanks for both your and Richard's comments.

                          try:
                                        ID_check = entry[0]
                                        print entry[0]
                                        intable = "in_memory\ID_Check"
                                        counter = 0
                                        with da.SearchCursor(intable,["ID"]) as cursor:
                                            for row in cursor:
                                                if row[0] == ID_check:
                                                    counter += 1
                                                   
                                        if counter >= 1:
                                            pythonaddins.MessageBox("This Feature's ID is a duplicate.  Solve thi                                                                                s error before continuing!","Error",0)
                                            raise Exception()
                                       
                                        elif counter == 0:
                                            print "All is good, this ID is not a duplicate."
                                            cursor = arcpy.da.InsertCursor(intable,["ID"])
                                            cursor.insertRow([ID_check])
                                            del cursor

                                            edit = da.Editor(workspace)
                                            edit.startEditing(False,True)
                                            edit.startOperation()
                                           
                                            with da.UpdateCursor(targetlayer,fields) as cursor:
                                                for row in cursor:
                                                    row = entry
                                                    print "row: {}".format(row)
                                                    cursor.updateRow(row)
                                                   
                                            del cursor
                                            del row
                                            edit.stopOperation()
                                            #edit.stopEditing(True)
                                           
                                           
                                    except Exception as e:
                                        print e.message
                                        print arcpy.GetMessages()
                                       
                                    arcpy.RefreshActiveView()
                                    print "Complete"
                               


When using "print edit.isEditing" after each edit method they are all true.  When I uncomment the line edit.stopEditing(True) an exception is thrown before the print statement saying Start Edit Session.  This happens in a versioned sde environment.  When using the same code in a personal geodatabase the exception message states something like "unable to perform within an edit session."

So my solution for sde is to comment out the stop editing method.  This works however if I create a feature then save edits.  If I later change the attributes or geometry of that feature the state of the geodatabase changes and the edits cannot be saved.  "Attempting to perform action on a closed state.  Unable to save edits."
0 Kudos
TimElliott
Occasional Contributor

From my research into this the cursor is locking itself out due to the auto commit. Interestingly setting it to 0 doesn't work so I just set it stupid high and it has resolved in my use case.

arcpy.env.autoCommit = 1000000

 

0 Kudos