I have a script (running/deving it in Pro 2.9, will eventually be scheduled) that is gathering data from other SDE tables into a dictionary row, and then updating a traditionally versioned feature class (10.9.1 gdb) with that data. I am connected via a child version of default using the data owner user. When my script attempts to update a row, I get the error message in the title. I cannot for the life of me figure out why, or how to see more detail of the error. My related update code is as below:
SQL = "PPIN IS NOT NULL"
workspace = os.path.dirname(parcels)
workspace = os.path.dirname(workspace)
edit = arcpy.da.Editor(workspace)
edit.startEditing(with_undo=False, multiuser_mode=True)
edit.startOperation()
uParcel = arcpy.da.UpdateCursor(parcels, Pfields, SQL)
for row in uParcel :
PPIN = row[0]
newRow = parcelDict[PPIN]
if newRow == row[1:] :
print(PPIN)
else :
row[1:] = newRow
uParcel.updateRow(row)
Solved! Go to Solution.
ok, that's good... is the initial cursor instantiated like the update cursor is, like in your example?
uParcel = arcpy.da.UpdateCursor(parcels, Pfields, SQL)
Is the cursor deleted after its used to create the list anywhere? It could be holding a lock on the fc and when you are trying to update it, still thinks you are in SearchCursor mode and internal code is crossing.
Try the with syntax in your cursors?
with arcpy.da.SearchCursor(fc, fields) as sCur:
or del the first cursor to release it?
Are you moving up in the workspace path too far? Try removing line 4.
parcels is a feature class in a feature dataset, so going up twice gives me the gdb
If I remove line four, when it attempts line five I get: RuntimeError: cannot open workspace
That error means the operation you are trying to do is not appropriate for an updatecursor, and the format of the row[1:], makes it think you are trying to do an insert operation.
You need to assign each row index a value and then update the row.
So, I amended my code and I am receiving the same error:
69851
70075
RuntimeError: This type of cursor does not support this operation. For example, calling UpdateRow on a read-only cursor.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<string>", line 63, in <module>
SystemError: <method 'updateRow' of 'da.UpdateCursor' objects> returned a result with an error set
FWIW the un-amended code did work on a fgdb, just not the SDE. Amended code was run as follows :
for row in uParcel :
PPIN = row[0]
newRow = parcelDict[PPIN]
if newRow == row[1:] :
print(PPIN)
else :
#!row[1:] = newRow
row[1] = newRow[0]
row[2] = newRow[1]
row[3] = newRow[2]
row[4] = newRow[3]
row[5] = newRow[4]
row[6] = newRow[5]
row[7] = newRow[6]
row[8] = newRow[7]
row[9] = newRow[8]
row[10] = newRow[9]
row[11] = newRow[10]
row[12] = newRow[11]
row[13] = newRow[12]
row[14] = newRow[13]
row[15] = newRow[14]
row[16] = newRow[15]
row[17] = newRow[16]
row[18] = newRow[17]
row[19] = newRow[18]
row[20] = newRow[19]
row[21] = newRow[20]
row[22] = newRow[21]
row[23] = newRow[22]
row[24] = newRow[23]
row[25] = newRow[24]
row[26] = newRow[25]
row[27] = newRow[26]
row[28] = newRow[27]
row[29] = newRow[28]
row[30] = newRow[29]
row[31] = newRow[30]
row[32] = newRow[31]
row[33] = newRow[32]
row[34] = newRow[33]
row[35] = newRow[34]
row[36] = newRow[35]
row[37] = newRow[36]
row[38] = newRow[37]
row[39] = newRow[38]
row[40] = newRow[39]
row[41] = newRow[40]
row[42] = newRow[41]
row[43] = newRow[42]
row[44] = newRow[43]
row[45] = newRow[44]
row[46] = newRow[45]
row[47] = newRow[46]
row[48] = newRow[47]
row[49] = newRow[48]
row[50] = newRow[49]
row[51] = newRow[50]
row[52] = newRow[51]
row[53] = newRow[52]
row[54] = newRow[53]
try :
uParcel.updateRow(row)
I did at first go one index too far, but that threw an error that said as much and was corrected before clearing and restarting.
There goes my theory. Maybe it doesn't like a value or type in one of the fields and doesn't know how to handle it. Not sure how the parcelDict is being built, but I think you'd have a little more control using a dictionary instead of a list. Here is an alternative to create the dict and to coding out 50+ assignments:
# Create a dictionary of fields and values, using the objectid as key
sCur = arcpy.da.SearchCursor(fc, fields)
dct = {row[fields.index('OBJECTID')] : {k: v for k, v in zip(sCur.fields, row) if k != 'OBJECTID'} for row in sCur}
# update the featureclass by comparing dictionaries and updating if different
with arcpy.da.UpdateCursor(fc, fields) as uCur:
for row in uCur:
# get the current row as dictionary
currentRow = {k: v for k, v in zip(uCur.fields, row) if k != 'OBJECTID'}
# get the matching dict of old values, returns teh default None if nothing is found.
newRow = dct.get(row[0])
# compare for equality
if newRow == currentRow:
print(newRow['OBJECTID'])
else:
# iterate over the cursor fields and get/ assign the new values from the dictionary.
for fld in uCur.fields:
if fld != 'OBJECTID':
row[uCur.fields.index(fld)] = newRow[fld]
uCur.updateRow(row)
If a field type isn't right it lets me know. For background, the dictionary rows are initially read from the table the cursor is updating, then the script uses the key to check several other tables that contain relevant data, and update the corresponding list/row values stored at each key. Finally, if the dictionary list doesn't match the current row, it's attempting to update the row.
This exact script works fine on an fgdb copy of the same feature class, every field identical. It is only when attempted on the SDE table that it has this strange issue where an update cursor is apparently not allowed to update. I thought it might be in the edit session handling because that part is a bit newer to me, but I'm stumped as to why it breaks at .updateRow instead of when opening or saving the edit session.
ok, that's good... is the initial cursor instantiated like the update cursor is, like in your example?
uParcel = arcpy.da.UpdateCursor(parcels, Pfields, SQL)
Is the cursor deleted after its used to create the list anywhere? It could be holding a lock on the fc and when you are trying to update it, still thinks you are in SearchCursor mode and internal code is crossing.
Try the with syntax in your cursors?
with arcpy.da.SearchCursor(fc, fields) as sCur:
or del the first cursor to release it?
I'm not sure why this worked since I've not ever encountered this issue before, but changing it from initiating and deleting the update cursor both "manually" to using "with" did indeed resolve the problem. I believe it may be something specific to the enterprise deployment I was working on, because the environment seems to have been the variable.
Many thanks for your help!
This blows my mind!!!!
if I use the syntax
uParcel = arcpy.da.UpdateCursor(parcels, Pfields, SQL)
in query to modify 10 items, it works ok. As soon as i change the where clause to modify 23700 features, it gives me the error mentioned above.
then I change to the syntax:
with arcpy.da.UpdateCursor(parcels, Pfields, SQL)as uCursor:
if fu****ing works. This library is so unstable.