The following script works to update coordinates in my ArcGIS feature class, but if I run it twice in a row from ArcMap on the same geodatabase feature class, I get a "RuntimeError: Unexpected Operation[outputZoneTrack FeatureClass name]" error on the "updateCursor.updateRow(row)". If I run it on a dataset, then run it on a different dataset, I can then re-run it on the first dataset again with no problem. I just can't run it on the same dataset twice in a row. Why does this error occur when I run the script twice in a row on the same dataset?
outputZoneTrack = "C:\\Temp\\geodatabase.gdb\\ozt"
outputWorkspace = os.path.split(outputZoneTrack)[0]
outputZoneTrackName = os.path.split(outputZoneTrack)[1]
arcpy.env.overwriteOutput = True
if arcpy.Exists(outputZoneTrack):
arcpy.Delete_management(outputZoneTrack)
spatial_reference = arcpy.SpatialReference(4326) #Use WGS84 so coordinates are calculated in Lat/Long
with arcpy.da.UpdateCursor(outputZoneTrack, ["ZSTARTLAT", "ZSTARTLON", "ZENDLAT", "ZENDLON", "SHAPE@"], "", spatial_reference) as updateCursor:
for row in updateCursor:
row[0] = row[4].firstPoint.Y
row[1] = row[4].firstPoint.X
row[2] = row[4].lastPoint.Y
row[3] = row[4].lastPoint.X
updateCursor.updateRow(row)
mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
if lyr.name == "Segment Oil Zones":
if lyr.supports("DATASOURCE"):
lyr.replaceDataSource(outputWorkspace, "FILEGDB_WORKSPACE", outputZoneTrackName, True)
lyr.name = "Segment Oil Zones"
lyr.visible = True
arcpy.AddMessage("\nOiling Zone Snapped to ACP Segments: ON\n")
arcpy.RefreshTOC()
Note - this problem only occurs if the script is run from ArcMap and the feature class is loaded within the ArcMap TOC - I can run it multiple times in a row on the same dataset from ArcCatalog.
3 Answers 3
UPDATED. This works. The real issue this script could not be run twice in a row on the same feature class appears to have something to do with being locked by the layer in the current MXD after the 1st run. So I made the script to change the data path on that layer when running, then change it back at the end of the script.
arcpy.env.overwriteOutput = True
if arcpy.Exists(outputZoneTrack):
arcpy.Delete_management(outputZoneTrack)
outputZoneTrack = "C:\\Temp\\geodatabase.gdb\\ozt"
outputWorkspace = os.path.split(outputZoneTrack)[0]
outputZoneTrackName = os.path.split(outputZoneTrack)[1]
mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
if lyr.name == "Segment Oil Zones":
if lyr.supports("DATASOURCE"):
lyr.replaceDataSource(outputWorkspace, "FILEGDB_WORKSPACE", outputZoneTrackName + "_Temp", True)
lyr.name = "Segment Oil Zones TEMP"
lyr.visible = False
arcpy.AddMessage("\nOiling Zone Snapped to ACP Segments: OFF\n")
arcpy.RefreshTOC()
spatial_reference = arcpy.SpatialReference(4326) #Use WGS84 so coordinates are calculated in Lat/Long
with arcpy.da.UpdateCursor(outputZoneTrack, ["ZSTARTLAT", "ZSTARTLON", "ZENDLAT", "ZENDLON", "SHAPE@"], "", spatial_reference) as updateCursor:
for row in updateCursor:
row[0] = row[4].firstPoint.Y
row[1] = row[4].firstPoint.X
row[2] = row[4].lastPoint.Y
row[3] = row[4].lastPoint.X
updateCursor.updateRow(row)
mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
if lyr.name == "Segment Oil Zones TEMP":
if lyr.supports("DATASOURCE"):
lyr.replaceDataSource(outputWorkspace, "FILEGDB_WORKSPACE", outputZoneTrackName, True)
lyr.name = "Segment Oil Zones"
lyr.visible = True
arcpy.AddMessage("\nOiling Zone Snapped to ACP Segments: ON\n")
arcpy.RefreshTOC()
-
2
row
is a tuple, which is immutable. Addrow = list(row)
directly after the for loop and it should work without temp variable.Paul– Paul2017年02月16日 23:19:07 +00:00Commented Feb 16, 2017 at 23:19 -
@Paul You are right, that does work and is more elegant. That being the case, why would the script run fine the first time and only crash when being re-run consecutively on the same feature class?spaine– spaine2017年02月16日 23:34:15 +00:00Commented Feb 16, 2017 at 23:34
-
I have no idea. Python should be throwing
TypeError
unless you had the variablerow
floating around from earlier.Paul– Paul2017年02月16日 23:45:33 +00:00Commented Feb 16, 2017 at 23:45 -
It turns out that tuple was not related to the error - it had something to do with the layer in the MXD locking the feature class after the first time it was run. I've updated the answer accordingly.spaine– spaine2017年02月17日 20:56:07 +00:00Commented Feb 17, 2017 at 20:56
You are attempting to use outputZoneTrack
before it is defined. Try defining it before testing if it exists and before attempting to delete it. (I'm not certain this will fix your issue, but it does appear to be an issue that needs fixing.)
Ie, replace this:
arcpy.env.overwriteOutput = True
if arcpy.Exists(outputZoneTrack):
arcpy.Delete_management(outputZoneTrack)
outputZoneTrack = "C:\\Temp\\geodatabase.gdb\\ozt"
with this:
outputZoneTrack = "C:\\Temp\\geodatabase.gdb\\ozt"
arcpy.env.overwriteOutput = True
if arcpy.Exists(outputZoneTrack):
print "Deleting {}".format(outputZoneTrack)
arcpy.AddMessage("Deleting {}".format(outputZoneTrack))
arcpy.Delete_management(outputZoneTrack)
(I've also added debug lines, print
and AddMessage
, which will at least make it clear when it's actually running Delete_management
.)
-
2This may be the answer (I don't know) however it does appear that the code is part of a much larger script (see error message referring to line 178), and from the comments the asker has added the
outputZoneTrack = "C:\\Temp\\geodatabase.gdb\\ozt"
line for clarity2017年02月15日 07:07:25 +00:00Commented Feb 15, 2017 at 7:07
You are using an arcpy.da.cursor. They are notorious for putting schema locks on feature classes. You will need to delete your cursor at the end of the iteration to free up the schema lock.
del row
del updateCursor
You may just need to delete the cursor not the row.
-
I've tried that, it had no effect. Also, putting the cursor within a
with
statement should prevent that lock from persisting.spaine– spaine2017年02月17日 21:14:17 +00:00Commented Feb 17, 2017 at 21:14 -
You shouldn't need to use
del
if you're usingwith
statements.Paul– Paul2017年02月17日 21:53:05 +00:00Commented Feb 17, 2017 at 21:53
updateCursor.updateRow(row)
? Please edit your question to include any updatesoutputZoneTrack
when you are deleting it a few lines prior?