# Using arcpy.da.Editor correctly?

I am attempting to remove duplicates in a feature class that are generated by a Python script. At the end of my script I have the code block below; I haven't implemented it yet, but would like to see if this is the correct way to use arcpy.da.Editor as the errors that I have been receiving are in regards to being outside of an edit session.

Is arcpy.da.Editor being used correctly here?



        fields = ['OBJECTID', 'SRNumber', 'ItemLoc_9']

table_rows = []
delete_rows = []

where_clause =  """ ItemLoc_9 = ' '"""

with arcpy.da.Editor(appendClass) as edit:
with arcpy.da.SearchCursor(appendClass, fields, where_clause) as cursor:
for row in cursor:
if [row[1], row[2]] in table_rows:
delete_rows.append(row[0])
else:
table_rows.append([row[1], row[2]])

del table_rows

with arcpy.da.UpdateCursor(appendClass, ['OBJECTID']) as cursor2:
for row in cursor2:
if row[0] in delete_rows:
print 'Deleting record: OBJECTID = ' + str(row[0])
cursor2.deleteRow()

print '\ndone'


I remember having an issue using the Editor in the with statement, but I haven't tried it in awhile.

You might try this format instead:

edit = arcpy.da.Editor(workspace)
edit.startEditing(False, True)
edit.startOperation()

##CODE

edit.stopOperation()
edit.stopEditing(True)


I looked back at an old script, and that's the format I used.

I have had lots of trouble/inconsistencies with this in the past. Instead, I have implemented some wrappers for both the update and insert cursors. This way, every time I run an update cursor, I know an edit session is properly started and stopped for the cursor. Here is my update cursor (with a helper function to get the workspace):

import arcpy
import os

def find_ws(path, ws_type=''):
"""finds a valid workspace path for an arcpy.da.Editor() Session

Required:
path -- path to features or workspace

Optional:
ws_type -- option to find specific workspace type (FileSystem|LocalDatabase|RemoteDatabase)

"""
# try original path first
if os.sep not in path:
path = arcpy.Describe(path).catalogPath
desc = arcpy.Describe(path)
if hasattr(desc, 'workspaceType'):
if ws_type and ws_type == desc.workspaceType:
return path
elif not ws_type:
return path

# search until finding a valid workspace
SPLIT = filter(None, path.split(os.sep))
if path.startswith('\\\\'):
SPLIT[0] = r'\\{0}'.format(SPLIT[0])

# find valid workspace
for i in xrange(1, len(SPLIT)):
sub_dir = os.sep.join(SPLIT[:-i])
desc = arcpy.Describe(sub_dir)
if hasattr(desc, 'workspaceType'):
if ws_type and ws_type == desc.workspaceType:
return sub_dir
elif not ws_type:
return sub_dir

class UpdateCursor(object):
"""wrapper class for arcpy.da.UpdateCursor, to automatically
implement editing (required for versioned data, and data with
geometric networks, topologies, network datasets, and relationship
classes"""
def __init__(self, *args, **kwargs):
"""initiate wrapper class for update cursor.  Supported args:

in_table, field_names, where_clause=None, spatial_reference=None,
explode_to_points=False, sql_clause=(None, None)
"""
self.args = args
self.kwargs = kwargs
self.edit = None

def __enter__(self):
ws = None
if self.args:
ws = find_ws(self.args[0])
elif 'in_table' in self.kwargs:
ws = find_ws(self.kwargs['in_table'])
self.edit = arcpy.da.Editor(ws)
self.edit.startEditing()
self.edit.startOperation()
return arcpy.da.UpdateCursor(*self.args, **self.kwargs)

def __exit__(self, type, value, traceback):
self.edit.stopOperation()
self.edit.stopEditing(True)
self.edit = None


So if you save this somewhere in your PYTHONPATH and call the update cursor, you can always be sure that an edit session is started and stopped. This wrapper also allows the usage of the with statement for the cursor.

If you saved the script above as some_module.py and save it in your PYTHONPATH, you can call it like this:

import some_module

fc = r'C:\Path\to_your\FileGeodatabase\YourFC'
fields = ["field1", "field2"]

with some_module.UpdateCursor(fc, fields) as rows:
for row in rows:
row[1] = row[0]
rows.updateRow(row)

• If this solves my problem I will buy you a beer! – J. Nic 2 days ago
• It solved my problem! - PM me if you want a beer. This was a life-saver. – J. Nic yesterday
• @J.Nic glad it helped! I posted an updated version somewhere in the esri forums to that is updated for ArcGIS Pro/Python 3. I was unable to find that post in the new community system though. – crmackey yesterday

This will work on a versioned database feature class:

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, True)
# Create update cursor